@picovoice/eagle-web 0.1.1 → 0.2.0

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.
@@ -0,0 +1,252 @@
1
+ //
2
+ // Copyright 2023 Picovoice Inc.
3
+ //
4
+ // You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE"
5
+ // file accompanying this source.
6
+ //
7
+ // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
8
+ // an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
9
+ // specific language governing permissions and limitations under the License.
10
+ //
11
+
12
+ import { PvError } from '@picovoice/web-utils';
13
+ import { PvStatus } from './types';
14
+
15
+ class EagleError extends Error {
16
+ private readonly _status: PvStatus;
17
+ private readonly _shortMessage: string;
18
+ private readonly _messageStack: string[];
19
+
20
+ constructor(
21
+ status: PvStatus,
22
+ message: string,
23
+ messageStack: string[] = [],
24
+ pvError: PvError | null = null
25
+ ) {
26
+ super(EagleError.errorToString(message, messageStack, pvError));
27
+ this._status = status;
28
+ this.name = 'EagleError';
29
+ this._shortMessage = message;
30
+ this._messageStack = messageStack;
31
+ }
32
+
33
+ get status(): PvStatus {
34
+ return this._status;
35
+ }
36
+
37
+ get shortMessage(): string {
38
+ return this._shortMessage;
39
+ }
40
+
41
+ get messageStack(): string[] {
42
+ return this._messageStack;
43
+ }
44
+
45
+ private static errorToString(
46
+ initial: string,
47
+ messageStack: string[],
48
+ pvError: PvError | null = null
49
+ ): string {
50
+ let msg = initial;
51
+
52
+ if (pvError) {
53
+ const pvErrorMessage = pvError.getErrorString();
54
+ if (pvErrorMessage.length > 0) {
55
+ msg += `\nDetails: ${pvErrorMessage}`;
56
+ }
57
+ }
58
+
59
+ if (messageStack.length > 0) {
60
+ msg += `: ${messageStack.reduce(
61
+ (acc, value, index) => acc + '\n [' + index + '] ' + value,
62
+ ''
63
+ )}`;
64
+ }
65
+
66
+ return msg;
67
+ }
68
+ }
69
+
70
+ class EagleOutOfMemoryError extends EagleError {
71
+ constructor(
72
+ message: string,
73
+ messageStack?: string[],
74
+ pvError: PvError | null = null
75
+ ) {
76
+ super(PvStatus.OUT_OF_MEMORY, message, messageStack, pvError);
77
+ this.name = 'EagleOutOfMemoryError';
78
+ }
79
+ }
80
+
81
+ class EagleIOError extends EagleError {
82
+ constructor(
83
+ message: string,
84
+ messageStack: string[] = [],
85
+ pvError: PvError | null = null
86
+ ) {
87
+ super(PvStatus.IO_ERROR, message, messageStack, pvError);
88
+ this.name = 'EagleIOError';
89
+ }
90
+ }
91
+
92
+ class EagleInvalidArgumentError extends EagleError {
93
+ constructor(
94
+ message: string,
95
+ messageStack: string[] = [],
96
+ pvError: PvError | null = null
97
+ ) {
98
+ super(PvStatus.INVALID_ARGUMENT, message, messageStack, pvError);
99
+ this.name = 'EagleInvalidArgumentError';
100
+ }
101
+ }
102
+
103
+ class EagleStopIterationError extends EagleError {
104
+ constructor(
105
+ message: string,
106
+ messageStack: string[] = [],
107
+ pvError: PvError | null = null
108
+ ) {
109
+ super(PvStatus.STOP_ITERATION, message, messageStack, pvError);
110
+ this.name = 'EagleStopIterationError';
111
+ }
112
+ }
113
+
114
+ class EagleKeyError extends EagleError {
115
+ constructor(
116
+ message: string,
117
+ messageStack: string[] = [],
118
+ pvError: PvError | null = null
119
+ ) {
120
+ super(PvStatus.KEY_ERROR, message, messageStack, pvError);
121
+ this.name = 'EagleKeyError';
122
+ }
123
+ }
124
+
125
+ class EagleInvalidStateError extends EagleError {
126
+ constructor(
127
+ message: string,
128
+ messageStack: string[] = [],
129
+ pvError: PvError | null = null
130
+ ) {
131
+ super(PvStatus.INVALID_STATE, message, messageStack, pvError);
132
+ this.name = 'EagleInvalidStateError';
133
+ }
134
+ }
135
+
136
+ class EagleRuntimeError extends EagleError {
137
+ constructor(
138
+ message: string,
139
+ messageStack: string[] = [],
140
+ pvError: PvError | null = null
141
+ ) {
142
+ super(PvStatus.RUNTIME_ERROR, message, messageStack, pvError);
143
+ this.name = 'EagleRuntimeError';
144
+ }
145
+ }
146
+
147
+ class EagleActivationError extends EagleError {
148
+ constructor(
149
+ message: string,
150
+ messageStack: string[] = [],
151
+ pvError: PvError | null = null
152
+ ) {
153
+ super(PvStatus.ACTIVATION_ERROR, message, messageStack, pvError);
154
+ this.name = 'EagleActivationError';
155
+ }
156
+ }
157
+
158
+ class EagleActivationLimitReachedError extends EagleError {
159
+ constructor(
160
+ message: string,
161
+ messageStack: string[] = [],
162
+ pvError: PvError | null = null
163
+ ) {
164
+ super(PvStatus.ACTIVATION_LIMIT_REACHED, message, messageStack, pvError);
165
+ this.name = 'EagleActivationLimitReachedError';
166
+ }
167
+ }
168
+
169
+ class EagleActivationThrottledError extends EagleError {
170
+ constructor(
171
+ message: string,
172
+ messageStack: string[] = [],
173
+ pvError: PvError | null = null
174
+ ) {
175
+ super(PvStatus.ACTIVATION_THROTTLED, message, messageStack, pvError);
176
+ this.name = 'EagleActivationThrottledError';
177
+ }
178
+ }
179
+
180
+ class EagleActivationRefusedError extends EagleError {
181
+ constructor(
182
+ message: string,
183
+ messageStack: string[] = [],
184
+ pvError: PvError | null = null
185
+ ) {
186
+ super(PvStatus.ACTIVATION_REFUSED, message, messageStack, pvError);
187
+ this.name = 'EagleActivationRefusedError';
188
+ }
189
+ }
190
+
191
+ export {
192
+ EagleError,
193
+ EagleOutOfMemoryError,
194
+ EagleIOError,
195
+ EagleInvalidArgumentError,
196
+ EagleStopIterationError,
197
+ EagleKeyError,
198
+ EagleInvalidStateError,
199
+ EagleRuntimeError,
200
+ EagleActivationError,
201
+ EagleActivationLimitReachedError,
202
+ EagleActivationThrottledError,
203
+ EagleActivationRefusedError,
204
+ };
205
+
206
+ export function pvStatusToException(
207
+ pvStatus: PvStatus,
208
+ errorMessage: string,
209
+ messageStack: string[] = [],
210
+ pvError: PvError | null = null
211
+ ): EagleError {
212
+ switch (pvStatus) {
213
+ case PvStatus.OUT_OF_MEMORY:
214
+ return new EagleOutOfMemoryError(errorMessage, messageStack, pvError);
215
+ case PvStatus.IO_ERROR:
216
+ return new EagleIOError(errorMessage, messageStack, pvError);
217
+ case PvStatus.INVALID_ARGUMENT:
218
+ return new EagleInvalidArgumentError(errorMessage, messageStack, pvError);
219
+ case PvStatus.STOP_ITERATION:
220
+ return new EagleStopIterationError(errorMessage, messageStack, pvError);
221
+ case PvStatus.KEY_ERROR:
222
+ return new EagleKeyError(errorMessage, messageStack, pvError);
223
+ case PvStatus.INVALID_STATE:
224
+ return new EagleInvalidStateError(errorMessage, messageStack, pvError);
225
+ case PvStatus.RUNTIME_ERROR:
226
+ return new EagleRuntimeError(errorMessage, messageStack, pvError);
227
+ case PvStatus.ACTIVATION_ERROR:
228
+ return new EagleActivationError(errorMessage, messageStack, pvError);
229
+ case PvStatus.ACTIVATION_LIMIT_REACHED:
230
+ return new EagleActivationLimitReachedError(
231
+ errorMessage,
232
+ messageStack,
233
+ pvError
234
+ );
235
+ case PvStatus.ACTIVATION_THROTTLED:
236
+ return new EagleActivationThrottledError(
237
+ errorMessage,
238
+ messageStack,
239
+ pvError
240
+ );
241
+ case PvStatus.ACTIVATION_REFUSED:
242
+ return new EagleActivationRefusedError(
243
+ errorMessage,
244
+ messageStack,
245
+ pvError
246
+ );
247
+ default:
248
+ // eslint-disable-next-line no-console
249
+ console.warn(`Unmapped error code: ${pvStatus}`);
250
+ return new EagleError(pvStatus, errorMessage);
251
+ }
252
+ }
@@ -22,6 +22,7 @@ import {
22
22
  EagleProfilerWorkerResetResponse,
23
23
  } from './types';
24
24
  import { loadModel } from '@picovoice/web-utils';
25
+ import { pvStatusToException } from "./eagle_errors";
25
26
 
26
27
  export class EagleProfilerWorker {
27
28
  private readonly _worker: Worker;
@@ -31,6 +32,7 @@ export class EagleProfilerWorker {
31
32
 
32
33
  private static _wasm: string;
33
34
  private static _wasmSimd: string;
35
+ private static _sdk: string = "web";
34
36
 
35
37
  private constructor(
36
38
  worker: Worker,
@@ -85,6 +87,10 @@ export class EagleProfilerWorker {
85
87
  }
86
88
  }
87
89
 
90
+ public static setSdk(sdk: string): void {
91
+ EagleProfilerWorker._sdk = sdk;
92
+ }
93
+
88
94
  /**
89
95
  * Creates an instance of profiler component of the Eagle Speaker Recognition Engine.
90
96
  *
@@ -129,11 +135,11 @@ export class EagleProfilerWorker {
129
135
  break;
130
136
  case 'failed':
131
137
  case 'error':
132
- reject(event.data.message);
138
+ reject(pvStatusToException(event.data.status, event.data.shortMessage, event.data.messageStack));
133
139
  break;
134
140
  default:
135
141
  // @ts-ignore
136
- reject(`Unrecognized command: ${event.data.command}`);
142
+ reject(pvStatusToException(PvStatus.RUNTIME_ERROR, `Unrecognized command: ${event.data.command}`));
137
143
  }
138
144
  };
139
145
  }
@@ -145,6 +151,7 @@ export class EagleProfilerWorker {
145
151
  modelPath: modelPath,
146
152
  wasm: this._wasm,
147
153
  wasmSimd: this._wasmSimd,
154
+ sdk: this._sdk,
148
155
  });
149
156
 
150
157
  return returnPromise;
@@ -187,11 +194,11 @@ export class EagleProfilerWorker {
187
194
  break;
188
195
  case 'failed':
189
196
  case 'error':
190
- reject(event.data.message);
197
+ reject(pvStatusToException(event.data.status, event.data.shortMessage, event.data.messageStack));
191
198
  break;
192
199
  default:
193
200
  // @ts-ignore
194
- reject(`Unrecognized command: ${event.data.command}`);
201
+ reject(pvStatusToException(PvStatus.RUNTIME_ERROR, `Unrecognized command: ${event.data.command}`));
195
202
  }
196
203
  };
197
204
  }
@@ -223,11 +230,11 @@ export class EagleProfilerWorker {
223
230
  break;
224
231
  case 'failed':
225
232
  case 'error':
226
- reject(event.data.message);
233
+ reject(pvStatusToException(event.data.status, event.data.shortMessage, event.data.messageStack));
227
234
  break;
228
235
  default:
229
236
  // @ts-ignore
230
- reject(`Unrecognized command: ${event.data.command}`);
237
+ reject(pvStatusToException(PvStatus.RUNTIME_ERROR, `Unrecognized command: ${event.data.command}`));
231
238
  }
232
239
  };
233
240
  }
@@ -254,11 +261,11 @@ export class EagleProfilerWorker {
254
261
  break;
255
262
  case 'failed':
256
263
  case 'error':
257
- reject(event.data.message);
264
+ reject(pvStatusToException(event.data.status, event.data.shortMessage, event.data.messageStack));
258
265
  break;
259
266
  default:
260
267
  // @ts-ignore
261
- reject(`Unrecognized command: ${event.data.command}`);
268
+ reject(pvStatusToException(PvStatus.RUNTIME_ERROR, `Unrecognized command: ${event.data.command}`));
262
269
  }
263
270
  };
264
271
  });
@@ -283,11 +290,11 @@ export class EagleProfilerWorker {
283
290
  break;
284
291
  case 'failed':
285
292
  case 'error':
286
- reject(event.data.message);
293
+ reject(pvStatusToException(event.data.status, event.data.shortMessage, event.data.messageStack));
287
294
  break;
288
295
  default:
289
296
  // @ts-ignore
290
- reject(`Unrecognized command: ${event.data.command}`);
297
+ reject(pvStatusToException(PvStatus.RUNTIME_ERROR, `Unrecognized command: ${event.data.command}`));
291
298
  }
292
299
  };
293
300
  });
@@ -15,7 +15,9 @@ import {
15
15
  EagleProfilerWorkerEnrollRequest,
16
16
  EagleProfilerWorkerInitRequest,
17
17
  EagleProfilerWorkerRequest,
18
+ PvStatus,
18
19
  } from './types';
20
+ import { EagleError } from "./eagle_errors";
19
21
 
20
22
  let profiler: EagleProfiler | null = null;
21
23
 
@@ -25,12 +27,14 @@ const initRequest = async (
25
27
  if (profiler !== null) {
26
28
  return {
27
29
  command: 'error',
28
- message: 'Eagle profiler already initialized',
30
+ status: PvStatus.INVALID_STATE,
31
+ shortMessage: 'Eagle profiler already initialized',
29
32
  };
30
33
  }
31
34
  try {
32
35
  EagleProfiler.setWasm(request.wasm);
33
36
  EagleProfiler.setWasmSimd(request.wasmSimd);
37
+ EagleProfiler.setSdk(request.sdk);
34
38
  profiler = await EagleProfiler._init(request.accessKey, request.modelPath);
35
39
  return {
36
40
  command: 'ok',
@@ -39,10 +43,20 @@ const initRequest = async (
39
43
  version: profiler.version,
40
44
  };
41
45
  } catch (e: any) {
42
- return {
43
- command: 'error',
44
- message: e.message,
45
- };
46
+ if (e instanceof EagleError) {
47
+ return {
48
+ command: 'error',
49
+ status: e.status,
50
+ shortMessage: e.shortMessage,
51
+ messageStack: e.messageStack
52
+ };
53
+ } else {
54
+ return {
55
+ command: 'error',
56
+ status: PvStatus.RUNTIME_ERROR,
57
+ shortMessage: e.message
58
+ };
59
+ }
46
60
  }
47
61
  };
48
62
 
@@ -52,7 +66,8 @@ const enrollRequest = async (
52
66
  if (profiler === null) {
53
67
  return {
54
68
  command: 'error',
55
- message: 'Eagle profiler not initialized',
69
+ status: PvStatus.INVALID_STATE,
70
+ shortMessage: 'Eagle profiler not initialized',
56
71
  };
57
72
  }
58
73
  try {
@@ -62,10 +77,20 @@ const enrollRequest = async (
62
77
  result,
63
78
  };
64
79
  } catch (e: any) {
65
- return {
66
- command: 'error',
67
- message: e.message,
68
- };
80
+ if (e instanceof EagleError) {
81
+ return {
82
+ command: 'error',
83
+ status: e.status,
84
+ shortMessage: e.shortMessage,
85
+ messageStack: e.messageStack
86
+ };
87
+ } else {
88
+ return {
89
+ command: 'error',
90
+ status: PvStatus.RUNTIME_ERROR,
91
+ shortMessage: e.message
92
+ };
93
+ }
69
94
  }
70
95
  };
71
96
 
@@ -73,7 +98,8 @@ const exportRequest = async (): Promise<any> => {
73
98
  if (profiler === null) {
74
99
  return {
75
100
  command: 'error',
76
- message: 'Eagle profiler not initialized',
101
+ status: PvStatus.INVALID_STATE,
102
+ shortMessage: 'Eagle profiler not initialized',
77
103
  };
78
104
  }
79
105
  try {
@@ -83,10 +109,20 @@ const exportRequest = async (): Promise<any> => {
83
109
  profile,
84
110
  };
85
111
  } catch (e: any) {
86
- return {
87
- command: 'error',
88
- message: e.message,
89
- };
112
+ if (e instanceof EagleError) {
113
+ return {
114
+ command: 'error',
115
+ status: e.status,
116
+ shortMessage: e.shortMessage,
117
+ messageStack: e.messageStack
118
+ };
119
+ } else {
120
+ return {
121
+ command: 'error',
122
+ status: PvStatus.RUNTIME_ERROR,
123
+ shortMessage: e.message
124
+ };
125
+ }
90
126
  }
91
127
  };
92
128
 
@@ -94,7 +130,8 @@ const resetRequest = async (): Promise<any> => {
94
130
  if (profiler === null) {
95
131
  return {
96
132
  command: 'error',
97
- message: 'Eagle not initialized',
133
+ status: PvStatus.INVALID_STATE,
134
+ shortMessage: 'Eagle profiler not initialized',
98
135
  };
99
136
  }
100
137
  try {
@@ -103,10 +140,20 @@ const resetRequest = async (): Promise<any> => {
103
140
  command: 'ok',
104
141
  };
105
142
  } catch (e: any) {
106
- return {
107
- command: 'error',
108
- message: e.message,
109
- };
143
+ if (e instanceof EagleError) {
144
+ return {
145
+ command: 'error',
146
+ status: e.status,
147
+ shortMessage: e.shortMessage,
148
+ messageStack: e.messageStack
149
+ };
150
+ } else {
151
+ return {
152
+ command: 'error',
153
+ status: PvStatus.RUNTIME_ERROR,
154
+ shortMessage: e.message
155
+ };
156
+ }
110
157
  }
111
158
  };
112
159
 
@@ -20,6 +20,7 @@ import {
20
20
  EagleProfile,
21
21
  } from './types';
22
22
  import { loadModel } from '@picovoice/web-utils';
23
+ import { pvStatusToException } from "./eagle_errors";
23
24
 
24
25
  export class EagleWorker {
25
26
  private readonly _worker: Worker;
@@ -29,6 +30,7 @@ export class EagleWorker {
29
30
 
30
31
  private static _wasm: string;
31
32
  private static _wasmSimd: string;
33
+ private static _sdk: string = "web";
32
34
 
33
35
  private constructor(
34
36
  worker: Worker,
@@ -83,10 +85,14 @@ export class EagleWorker {
83
85
  }
84
86
  }
85
87
 
88
+ public static setSdk(sdk: string): void {
89
+ EagleWorker._sdk = sdk;
90
+ }
91
+
86
92
  /**
87
93
  * Creates an instance of the Picovoice Eagle Speaker Recognition Engine.
88
94
  *
89
- * @param accessKey: AccessKey obtained from Picovoice Console (https://console.picovoice.ai/)
95
+ * @param accessKey AccessKey obtained from Picovoice Console (https://console.picovoice.ai/)
90
96
  * @param model Eagle model options.
91
97
  * @param model.base64 The model in base64 string to initialize Eagle.
92
98
  * @param model.publicPath The model path relative to the public directory.
@@ -129,11 +135,11 @@ export class EagleWorker {
129
135
  break;
130
136
  case 'failed':
131
137
  case 'error':
132
- reject(event.data.message);
138
+ reject(pvStatusToException(event.data.status, event.data.shortMessage, event.data.messageStack));
133
139
  break;
134
140
  default:
135
141
  // @ts-ignore
136
- reject(`Unrecognized command: ${event.data.command}`);
142
+ reject(pvStatusToException(PvStatus.RUNTIME_ERROR, `Unrecognized command: ${event.data.command}`));
137
143
  }
138
144
  };
139
145
  }
@@ -148,6 +154,7 @@ export class EagleWorker {
148
154
  : speakerProfiles,
149
155
  wasm: this._wasm,
150
156
  wasmSimd: this._wasmSimd,
157
+ sdk: this._sdk,
151
158
  });
152
159
 
153
160
  return returnPromise;
@@ -174,11 +181,11 @@ export class EagleWorker {
174
181
  break;
175
182
  case 'failed':
176
183
  case 'error':
177
- reject(event.data.message);
184
+ reject(pvStatusToException(event.data.status, event.data.shortMessage, event.data.messageStack));
178
185
  break;
179
186
  default:
180
187
  // @ts-ignore
181
- reject(`Unrecognized command: ${event.data.command}`);
188
+ reject(pvStatusToException(PvStatus.RUNTIME_ERROR, `Unrecognized command: ${event.data.command}`));
182
189
  }
183
190
  };
184
191
  });
@@ -206,11 +213,11 @@ export class EagleWorker {
206
213
  break;
207
214
  case 'failed':
208
215
  case 'error':
209
- reject(event.data.message);
216
+ reject(pvStatusToException(event.data.status, event.data.shortMessage, event.data.messageStack));
210
217
  break;
211
218
  default:
212
219
  // @ts-ignore
213
- reject(`Unrecognized command: ${event.data.command}`);
220
+ reject(pvStatusToException(PvStatus.RUNTIME_ERROR, `Unrecognized command: ${event.data.command}`));
214
221
  }
215
222
  };
216
223
  });
@@ -235,11 +242,11 @@ export class EagleWorker {
235
242
  break;
236
243
  case 'failed':
237
244
  case 'error':
238
- reject(event.data.message);
245
+ reject(pvStatusToException(event.data.status, event.data.shortMessage, event.data.messageStack));
239
246
  break;
240
247
  default:
241
248
  // @ts-ignore
242
- reject(`Unrecognized command: ${event.data.command}`);
249
+ reject(pvStatusToException(PvStatus.RUNTIME_ERROR, `Unrecognized command: ${event.data.command}`));
243
250
  }
244
251
  };
245
252
  });