assemblyai 1.0.1 → 2.0.1-beta

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.
Files changed (53) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +192 -83
  3. package/dist/index.d.ts +4 -0
  4. package/dist/index.esm.js +473 -0
  5. package/dist/index.js +482 -0
  6. package/dist/services/base.d.ts +13 -0
  7. package/dist/services/files/index.d.ts +9 -0
  8. package/dist/services/index.d.ts +29 -0
  9. package/dist/services/lemur/index.d.ts +8 -0
  10. package/dist/services/realtime/factory.d.ts +10 -0
  11. package/dist/services/realtime/index.d.ts +2 -0
  12. package/dist/services/realtime/service.d.ts +22 -0
  13. package/dist/services/transcripts/index.d.ts +59 -0
  14. package/dist/types/asyncapi.generated.d.ts +87 -0
  15. package/dist/types/index.d.ts +5 -0
  16. package/dist/types/openapi.generated.d.ts +685 -0
  17. package/dist/types/realtime/index.d.ts +36 -0
  18. package/dist/types/services/abstractions.d.ts +52 -0
  19. package/dist/types/services/index.d.ts +6 -0
  20. package/dist/types/transcripts/index.d.ts +5 -0
  21. package/dist/utils/axios.d.ts +3 -0
  22. package/dist/utils/errors/index.d.ts +1 -0
  23. package/dist/utils/errors/realtime.d.ts +23 -0
  24. package/package.json +58 -21
  25. package/src/index.ts +5 -0
  26. package/src/services/base.ts +14 -0
  27. package/src/services/files/index.ts +22 -0
  28. package/src/services/index.ts +49 -0
  29. package/src/services/lemur/index.ts +49 -0
  30. package/src/services/realtime/factory.ts +32 -0
  31. package/src/services/realtime/index.ts +2 -0
  32. package/src/services/realtime/service.ts +184 -0
  33. package/src/services/transcripts/index.ts +178 -0
  34. package/src/types/asyncapi.generated.ts +124 -0
  35. package/src/types/index.ts +5 -0
  36. package/src/types/openapi.generated.ts +834 -0
  37. package/src/types/realtime/index.ts +68 -0
  38. package/src/types/services/abstractions.ts +56 -0
  39. package/src/types/services/index.ts +7 -0
  40. package/src/types/transcripts/index.ts +5 -0
  41. package/src/utils/.gitkeep +0 -0
  42. package/src/utils/axios.ts +19 -0
  43. package/src/utils/errors/index.ts +5 -0
  44. package/src/utils/errors/realtime.ts +45 -0
  45. package/.eslintrc.json +0 -3
  46. package/index.js +0 -15
  47. package/src/Client.js +0 -28
  48. package/src/api/Http/Request.js +0 -108
  49. package/src/api/Http/Response.js +0 -23
  50. package/src/api/Model.js +0 -17
  51. package/src/api/Transcript.js +0 -16
  52. package/src/api/Upload.js +0 -41
  53. package/src/api/util.js +0 -48
@@ -0,0 +1,36 @@
1
+ import { FinalTranscript, PartialTranscript, RealtimeTranscript, RealtimeTranscriptType } from "../asyncapi.generated";
2
+ type CreateRealtimeServiceParams = {
3
+ realtimeUrl?: string;
4
+ sampleRate?: number;
5
+ wordBoost?: string[];
6
+ } & ({
7
+ apiKey?: string;
8
+ } | {
9
+ token: string;
10
+ });
11
+ type RealtimeServiceParams = {
12
+ realtimeUrl?: string;
13
+ sampleRate?: number;
14
+ wordBoost?: string[];
15
+ } & ({
16
+ apiKey: string;
17
+ } | {
18
+ token: string;
19
+ });
20
+ type RealtimeEvents = "open" | "close" | "transcript" | "transcript.partial" | "transcript.final" | "error";
21
+ type SessionBeginsEventData = {
22
+ sessionId: string;
23
+ expiresAt: Date;
24
+ };
25
+ type RealtimeListeners = {
26
+ open?: (event: SessionBeginsEventData) => void;
27
+ close?: (code: number, reason: string) => void;
28
+ transcript?: (transcript: RealtimeTranscript) => void;
29
+ "transcript.partial"?: (transcript: PartialTranscript) => void;
30
+ "transcript.final"?: (transcript: FinalTranscript) => void;
31
+ error?: (error: Error) => void;
32
+ };
33
+ type RealtimeTokenParams = {
34
+ expires_in: number;
35
+ };
36
+ export type { CreateRealtimeServiceParams, RealtimeServiceParams, RealtimeEvents, RealtimeTranscriptType, SessionBeginsEventData, RealtimeListeners, RealtimeTokenParams, };
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Interface for classes that can create resources.
3
+ * @template T The type of the resource.
4
+ * @template Parameters The type of the parameters required to create the resource.
5
+ */
6
+ interface Createable<T, Parameters, Options = Record<string, any>> {
7
+ /**
8
+ * Create a new resource.
9
+ * @param params The parameters of the new resource.
10
+ * @param options The options used for creating the new resource.
11
+ * @return A promise that resolves to the newly created resource.
12
+ */
13
+ create(params: Parameters, options?: Options): Promise<T>;
14
+ }
15
+ /**
16
+ * Interface for classes that can retrieve resources.
17
+ * @template T The type of the resource.
18
+ * @template Id The type of the resource's identifier. Defaults to string.
19
+ */
20
+ interface Retrieveable<T, Id = string> {
21
+ /**
22
+ * Get a resource.
23
+ * @param id The identifier of the resource to retrieve.
24
+ * @return A promise that resolves to the retrieved resource.
25
+ */
26
+ get(id: Id): Promise<T>;
27
+ }
28
+ /**
29
+ * Interface for classes that can delete resources.
30
+ * @template T The type of the resource.
31
+ * @template Id The type of the resource's identifier. Defaults to string.
32
+ */
33
+ interface Deletable<T, Id = string> {
34
+ /**
35
+ * Delete a resource.
36
+ * @param id The identifier of the resource to delete.
37
+ * @return A promise that resolves to a boolean indicating whether the deletion was successful.
38
+ */
39
+ delete(id: Id): Promise<T>;
40
+ }
41
+ /**
42
+ * Interface for classes that can list resources.
43
+ * @template T The type of the resource.
44
+ */
45
+ interface Listable<T, Page = string> {
46
+ /**
47
+ * List all resources.
48
+ * @return A promise that resolves to an array of resources.
49
+ */
50
+ list(page?: Page): Promise<T>;
51
+ }
52
+ export type { Createable, Retrieveable, Deletable, Listable };
@@ -0,0 +1,6 @@
1
+ type BaseServiceParams = {
2
+ apiKey: string;
3
+ baseUrl?: string;
4
+ };
5
+ export type * from "./abstractions";
6
+ export type { BaseServiceParams };
@@ -0,0 +1,5 @@
1
+ export type CreateTranscriptOptions = {
2
+ poll?: boolean;
3
+ pollingInterval?: number;
4
+ pollingTimeout?: number;
5
+ };
@@ -0,0 +1,3 @@
1
+ import { BaseServiceParams } from "../.";
2
+ export declare function createAxiosClient(params: BaseServiceParams): import("axios").AxiosInstance;
3
+ export declare function throwApiError(error: unknown): Promise<never>;
@@ -0,0 +1 @@
1
+ export { default as RealtimeError, RealtimeErrorType, RealtimeErrorMessages, } from "./realtime";
@@ -0,0 +1,23 @@
1
+ declare enum RealtimeErrorType {
2
+ BadSampleRate = 4000,
3
+ AuthFailed = 4001,
4
+ InsufficientFundsOrFreeAccount = 4002,
5
+ NonexistentSessionId = 4004,
6
+ SessionExpired = 4008,
7
+ ClosedSession = 4010,
8
+ RateLimited = 4029,
9
+ UniqueSessionViolation = 4030,
10
+ SessionTimeout = 4031,
11
+ AudioTooShort = 4032,
12
+ AudioTooLong = 4033,
13
+ BadJson = 4100,
14
+ BadSchema = 4101,
15
+ TooManyStreams = 4102,
16
+ Reconnected = 4103,
17
+ ReconnectAttemptsExhausted = 1013
18
+ }
19
+ declare const RealtimeErrorMessages: Record<RealtimeErrorType, string>;
20
+ declare class RealtimeError extends Error {
21
+ }
22
+ export { RealtimeErrorType, RealtimeErrorMessages };
23
+ export default RealtimeError;
package/package.json CHANGED
@@ -1,31 +1,68 @@
1
1
  {
2
2
  "name": "assemblyai",
3
- "version": "1.0.1",
4
- "description": "",
5
- "main": "index.js",
6
- "scripts": {
7
- "test": "echo \"Error: no test specified\" && exit 1"
8
- },
3
+ "version": "2.0.1-beta",
4
+ "description": "The AssemblyAI Node.js SDK provides an easy-to-use interface for interacting with the AssemblyAI API, which supports async and real-time transcription, as well as the latest LeMUR models.",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.esm.js",
7
+ "types": "dist/index.d.ts",
8
+ "typings": "dist/index.d.ts",
9
9
  "repository": {
10
10
  "type": "git",
11
- "url": "git+https://github.com/AssemblyAI/assemblyai-node-sdk.git"
11
+ "url": "git+https://github.com/AssemblyAI/assemblyai-typescript-sdk.git"
12
12
  },
13
- "keywords": [],
14
- "author": "",
15
- "license": "ISC",
16
- "bugs": {
17
- "url": "https://github.com/AssemblyAI/assemblyai-node-sdk/issues"
13
+ "publishConfig": {
14
+ "tag": "beta",
15
+ "access": "public",
16
+ "registry": "https://registry.npmjs.org/"
18
17
  },
19
- "homepage": "https://github.com/AssemblyAI/assemblyai-node-sdk#readme",
20
- "dependencies": {
21
- "request": "^2.88.0"
18
+ "scripts": {
19
+ "build": "pnpm clean && pnpm rollup -c",
20
+ "clean": "rimraf dist",
21
+ "lint": "tslint -p tsconfig.json",
22
+ "test": "pnpm lint && pnpm test:unit",
23
+ "test:unit": "jest --config jest.config.rollup.ts",
24
+ "prettier": "prettier --write 'src/**/*.ts'",
25
+ "generate-types": "tsx ./scripts/generate-types.ts && pnpm prettier"
22
26
  },
27
+ "keywords": [
28
+ "AssemblyAI",
29
+ "Speech-to-text"
30
+ ],
31
+ "author": "AssemblyAI (https://www.assemblyai.com)",
32
+ "license": "MIT",
33
+ "homepage": "https://www.assemblyai.com/docs",
34
+ "files": [
35
+ "dist",
36
+ "src",
37
+ "types"
38
+ ],
23
39
  "devDependencies": {
24
- "eslint": "^5.4.0",
25
- "eslint-config-standard": "^11.0.0",
26
- "eslint-plugin-import": "^2.14.0",
27
- "eslint-plugin-node": "^7.0.1",
28
- "eslint-plugin-promise": "^4.0.0",
29
- "eslint-plugin-standard": "^3.1.0"
40
+ "@types/jest": "^29.5.5",
41
+ "@types/node": "^20.5.7",
42
+ "@types/ws": "^8.5.5",
43
+ "dotenv": "^16.3.1",
44
+ "eslint": "^8.43.0",
45
+ "i": "^0.3.7",
46
+ "jest": "^29.5.0",
47
+ "jest-cli": "^29.5.0",
48
+ "jest-junit": "^16.0.0",
49
+ "jest-mock-extended": "^3.0.4",
50
+ "jest-websocket-mock": "^2.4.1",
51
+ "mock-socket": "^9.2.1",
52
+ "npm": "^9.7.1",
53
+ "openapi-typescript": "^6.6.1",
54
+ "prettier": "^2.8.8",
55
+ "rimraf": "^5.0.1",
56
+ "rollup": "^3.25.1",
57
+ "rollup-plugin-typescript2": "^0.34.1",
58
+ "ts-jest": "^29.1.0",
59
+ "ts-node": "^10.9.1",
60
+ "tslib": "^2.5.3",
61
+ "tslint": "^6.1.3",
62
+ "typescript": "^5.2.2"
63
+ },
64
+ "dependencies": {
65
+ "axios": "^1.4.0",
66
+ "ws": "^8.13.0"
30
67
  }
31
68
  }
package/src/index.ts ADDED
@@ -0,0 +1,5 @@
1
+ import AssemblyAI from "./services";
2
+
3
+ export * from "./services";
4
+ export type * from "./types";
5
+ export default AssemblyAI;
@@ -0,0 +1,14 @@
1
+ import { AxiosInstance } from "axios";
2
+
3
+ /**
4
+ * Base class for services that communicate with the API.
5
+ */
6
+ abstract class BaseService {
7
+ /**
8
+ * Create a new service.
9
+ * @param params The AxiosInstance to send HTTP requests to the API.
10
+ */
11
+ constructor(protected client: AxiosInstance) {}
12
+ }
13
+
14
+ export default BaseService;
@@ -0,0 +1,22 @@
1
+ import { readFile } from "fs/promises";
2
+ import BaseService from "@/services/base";
3
+ import { UploadedFile } from "@/types";
4
+
5
+ export default class FileService extends BaseService {
6
+ /**
7
+ * Upload a local file to AssemblyAI.
8
+ * @param path The local file to upload.
9
+ * @return A promise that resolves to the uploaded file URL.
10
+ */
11
+ async upload(path: string): Promise<string> {
12
+ const file = await readFile(path);
13
+
14
+ const { data } = await this.client.post<UploadedFile>("/v2/upload", file, {
15
+ headers: {
16
+ "Content-Type": "application/octet-stream",
17
+ },
18
+ });
19
+
20
+ return data.upload_url;
21
+ }
22
+ }
@@ -0,0 +1,49 @@
1
+ import { createAxiosClient } from "@/utils/axios";
2
+ import { BaseServiceParams } from "@/types";
3
+ import LemurService from "./lemur";
4
+ import { RealtimeService, RealtimeServiceFactory } from "./realtime";
5
+ import TranscriptService from "./transcripts";
6
+ import FileService from "./files";
7
+
8
+ export default class AssemblyAI {
9
+ /**
10
+ * The files service.
11
+ */
12
+ public files: FileService;
13
+
14
+ /**
15
+ * The transcripts service.
16
+ */
17
+ public transcripts: TranscriptService;
18
+
19
+ /**
20
+ * The LeMUR service.
21
+ */
22
+ public lemur: LemurService;
23
+
24
+ /**
25
+ * The realtime service.
26
+ */
27
+ public realtime: RealtimeServiceFactory;
28
+
29
+ /**
30
+ * Create a new AssemblyAI client.
31
+ * @param params The parameters for the service, including the API key and base URL, if any.
32
+ */
33
+ constructor(params: BaseServiceParams) {
34
+ params.baseUrl = params.baseUrl || "https://api.assemblyai.com";
35
+ const client = createAxiosClient(params);
36
+ this.files = new FileService(client);
37
+ this.transcripts = new TranscriptService(client, this.files);
38
+ this.lemur = new LemurService(client);
39
+ this.realtime = new RealtimeServiceFactory(client, params);
40
+ }
41
+ }
42
+
43
+ export {
44
+ LemurService,
45
+ RealtimeServiceFactory,
46
+ RealtimeService,
47
+ TranscriptService,
48
+ FileService,
49
+ };
@@ -0,0 +1,49 @@
1
+ import {
2
+ LemurSummaryParameters,
3
+ LemurActionItemsParameters,
4
+ LemurQuestionAnswerParameters,
5
+ LemurTaskParameters,
6
+ LemurSummaryResponse,
7
+ LemurQuestionAnswerResponse,
8
+ LemurActionItemsResponse,
9
+ LemurTaskResponse,
10
+ } from "@/types";
11
+ import BaseService from "@/services/base";
12
+
13
+ export default class LemurService extends BaseService {
14
+ async summary(params: LemurSummaryParameters): Promise<LemurSummaryResponse> {
15
+ const { data } = await this.client.post<LemurSummaryResponse>(
16
+ "/lemur/v3/generate/summary",
17
+ params
18
+ );
19
+ return data;
20
+ }
21
+
22
+ async questionAnswer(
23
+ params: LemurQuestionAnswerParameters
24
+ ): Promise<LemurQuestionAnswerResponse> {
25
+ const { data } = await this.client.post<LemurQuestionAnswerResponse>(
26
+ "/lemur/v3/generate/question-answer",
27
+ params
28
+ );
29
+ return data;
30
+ }
31
+
32
+ async actionItems(
33
+ params: LemurActionItemsParameters
34
+ ): Promise<LemurActionItemsResponse> {
35
+ const { data } = await this.client.post<LemurActionItemsResponse>(
36
+ "/lemur/v3/generate/action-items",
37
+ params
38
+ );
39
+ return data;
40
+ }
41
+
42
+ async task(params: LemurTaskParameters): Promise<LemurTaskResponse> {
43
+ const { data } = await this.client.post<LemurTaskResponse>(
44
+ "/lemur/v3/generate/task",
45
+ params
46
+ );
47
+ return data;
48
+ }
49
+ }
@@ -0,0 +1,32 @@
1
+ import {
2
+ BaseServiceParams,
3
+ RealtimeTokenParams,
4
+ CreateRealtimeServiceParams,
5
+ RealtimeServiceParams,
6
+ } from "@/types";
7
+ import { AxiosInstance } from "axios";
8
+ import { RealtimeService } from "./service";
9
+
10
+ export class RealtimeServiceFactory {
11
+ constructor(
12
+ private client: AxiosInstance,
13
+ private params: BaseServiceParams
14
+ ) {}
15
+
16
+ createService(params?: CreateRealtimeServiceParams): RealtimeService {
17
+ if (!params) params = { apiKey: this.params.apiKey };
18
+ else if (!("token" in params) && !params.apiKey) {
19
+ params.apiKey = this.params.apiKey;
20
+ }
21
+
22
+ return new RealtimeService(params as RealtimeServiceParams);
23
+ }
24
+
25
+ async createTemporaryToken(params: RealtimeTokenParams) {
26
+ const response = await this.client.post<{ token: string }>(
27
+ "/v2/realtime/token",
28
+ params
29
+ );
30
+ return response.data.token;
31
+ }
32
+ }
@@ -0,0 +1,2 @@
1
+ export * from "@/services/realtime/factory";
2
+ export * from "@/services/realtime/service";
@@ -0,0 +1,184 @@
1
+ import WebSocket from "ws";
2
+ import {
3
+ RealtimeEvents,
4
+ RealtimeListeners,
5
+ RealtimeServiceParams,
6
+ RealtimeMessage,
7
+ RealtimeTranscript,
8
+ PartialTranscript,
9
+ FinalTranscript,
10
+ SessionBeginsEventData,
11
+ } from "@/types";
12
+ import {
13
+ RealtimeError,
14
+ RealtimeErrorMessages,
15
+ RealtimeErrorType,
16
+ } from "@/utils/errors";
17
+
18
+ const defaultRealtimeUrl = "wss://api.assemblyai.com/v2/realtime/ws";
19
+
20
+ export class RealtimeService {
21
+ private realtimeUrl: string;
22
+ private sampleRate: number;
23
+ private wordBoost?: string[];
24
+ private apiKey?: string;
25
+ private token?: string;
26
+ private socket?: WebSocket;
27
+ private listeners: RealtimeListeners = {};
28
+ private sessionTerminatedResolve?: () => void;
29
+
30
+ constructor(params: RealtimeServiceParams) {
31
+ this.realtimeUrl = params.realtimeUrl ?? defaultRealtimeUrl;
32
+ this.sampleRate = params.sampleRate ?? 16_000;
33
+ this.wordBoost = params.wordBoost;
34
+ this.realtimeUrl = params.realtimeUrl ?? defaultRealtimeUrl;
35
+ if ("apiKey" in params) this.apiKey = params.apiKey;
36
+ if ("token" in params) this.token = params.token;
37
+
38
+ if (!(this.apiKey || this.token)) {
39
+ throw new Error("API key or temporary token is required.");
40
+ }
41
+ }
42
+
43
+ private connectionUrl(): URL {
44
+ const url = new URL(this.realtimeUrl);
45
+
46
+ if (url.protocol !== "wss:") {
47
+ throw new Error("Invalid protocol, must be wss");
48
+ }
49
+
50
+ const searchParams = new URLSearchParams();
51
+ if (this.token) {
52
+ searchParams.set("token", this.token);
53
+ }
54
+ searchParams.set("sample_rate", this.sampleRate.toString());
55
+ if (this.wordBoost && this.wordBoost.length > 0) {
56
+ searchParams.set("word_boost", JSON.stringify(this.wordBoost));
57
+ }
58
+ url.search = searchParams.toString();
59
+
60
+ return url;
61
+ }
62
+
63
+ on(event: "open", listener: (event: SessionBeginsEventData) => void): void;
64
+ on(
65
+ event: "transcript",
66
+ listener: (transcript: RealtimeTranscript) => void
67
+ ): void;
68
+ on(
69
+ event: "transcript.partial",
70
+ listener: (transcript: PartialTranscript) => void
71
+ ): void;
72
+ on(
73
+ event: "transcript.final",
74
+ listener: (transcript: FinalTranscript) => void
75
+ ): void;
76
+ on(event: "error", listener: (error: Error) => void): void;
77
+ on(event: "close", listener: (code: number, reason: string) => void): void;
78
+ on(event: RealtimeEvents, listener: (...args: any[]) => void) {
79
+ this.listeners[event] = listener;
80
+ }
81
+
82
+ connect() {
83
+ return new Promise<SessionBeginsEventData>((resolve, _) => {
84
+ if (this.socket) {
85
+ throw new Error("Already connected");
86
+ }
87
+
88
+ const url = this.connectionUrl();
89
+
90
+ let headers;
91
+ if (this.token) {
92
+ headers = undefined;
93
+ } else if (this.apiKey) {
94
+ headers = { Authorization: this.apiKey };
95
+ }
96
+
97
+ this.socket = new WebSocket(url.toString(), { headers });
98
+
99
+ this.socket.onclose = ({ code, reason }: WebSocket.CloseEvent) => {
100
+ if (!reason) {
101
+ if (code in RealtimeErrorType) {
102
+ reason = RealtimeErrorMessages[code as RealtimeErrorType];
103
+ }
104
+ }
105
+ this.listeners.close?.(code, reason);
106
+ };
107
+
108
+ this.socket.onerror = (errorEvent: WebSocket.ErrorEvent) => {
109
+ if (errorEvent.error) this.listeners.error?.(errorEvent.error as Error);
110
+ else this.listeners.error?.(new Error(errorEvent.message));
111
+ };
112
+
113
+ this.socket.onmessage = ({ data }: WebSocket.MessageEvent) => {
114
+ const message = JSON.parse(data.toString()) as RealtimeMessage;
115
+ if ("error" in message) {
116
+ this.listeners.error?.(new RealtimeError(message.error));
117
+ return;
118
+ }
119
+ switch (message.message_type) {
120
+ case "SessionBegins": {
121
+ const openObject: SessionBeginsEventData = {
122
+ sessionId: message.session_id,
123
+ expiresAt: new Date(message.expires_at),
124
+ };
125
+ resolve(openObject);
126
+ this.listeners.open?.(openObject);
127
+ break;
128
+ }
129
+ case "PartialTranscript": {
130
+ // message.created is actually a string when coming from the socket
131
+ message.created = new Date(message.created);
132
+ this.listeners.transcript?.(message);
133
+ this.listeners["transcript.partial"]?.(message);
134
+ break;
135
+ }
136
+ case "FinalTranscript": {
137
+ // message.created is actually a string when coming from the socket
138
+ message.created = new Date(message.created);
139
+ this.listeners.transcript?.(message);
140
+ this.listeners["transcript.final"]?.(message);
141
+ break;
142
+ }
143
+ case "SessionTerminated": {
144
+ this.sessionTerminatedResolve?.();
145
+ break;
146
+ }
147
+ }
148
+ };
149
+ });
150
+ }
151
+
152
+ sendAudio(audio: ArrayBuffer) {
153
+ if (!this.socket || this.socket.readyState !== WebSocket.OPEN) {
154
+ throw new Error("Socket is not open for communication");
155
+ }
156
+
157
+ const payload = {
158
+ audio_data: Buffer.from(audio).toString("base64"),
159
+ };
160
+ this.socket.send(JSON.stringify(payload));
161
+ }
162
+
163
+ async close(waitForSessionTermination = true) {
164
+ if (this.socket) {
165
+ if (this.socket.readyState === WebSocket.OPEN) {
166
+ const terminateSessionMessage = `{"terminate_session": true}`;
167
+ if (waitForSessionTermination) {
168
+ const sessionTerminatedPromise = new Promise<void>((resolve, _) => {
169
+ this.sessionTerminatedResolve = resolve;
170
+ });
171
+ this.socket.send(terminateSessionMessage);
172
+ await sessionTerminatedPromise;
173
+ } else {
174
+ this.socket.send(terminateSessionMessage);
175
+ }
176
+ }
177
+ this.socket.removeAllListeners();
178
+ this.socket.close();
179
+ }
180
+
181
+ this.listeners = {};
182
+ this.socket = undefined;
183
+ }
184
+ }