assemblyai 4.4.2 → 4.4.4

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,274 @@
1
+ import ws from 'ws';
2
+
3
+ /******************************************************************************
4
+ Copyright (c) Microsoft Corporation.
5
+
6
+ Permission to use, copy, modify, and/or distribute this software for any
7
+ purpose with or without fee is hereby granted.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
10
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
12
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
14
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15
+ PERFORMANCE OF THIS SOFTWARE.
16
+ ***************************************************************************** */
17
+ /* global Reflect, Promise, SuppressedError, Symbol */
18
+
19
+
20
+ function __awaiter(thisArg, _arguments, P, generator) {
21
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
22
+ return new (P || (P = Promise))(function (resolve, reject) {
23
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
24
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
25
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
26
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
27
+ });
28
+ }
29
+
30
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
31
+ var e = new Error(message);
32
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
33
+ };
34
+
35
+ const { WritableStream } = typeof window !== "undefined"
36
+ ? window
37
+ : typeof global !== "undefined"
38
+ ? global
39
+ : globalThis;
40
+
41
+ const factory = (url, params) => new ws(url, params);
42
+
43
+ var RealtimeErrorType;
44
+ (function (RealtimeErrorType) {
45
+ RealtimeErrorType[RealtimeErrorType["BadSampleRate"] = 4000] = "BadSampleRate";
46
+ RealtimeErrorType[RealtimeErrorType["AuthFailed"] = 4001] = "AuthFailed";
47
+ // Both InsufficientFunds and FreeAccount error use 4002
48
+ RealtimeErrorType[RealtimeErrorType["InsufficientFundsOrFreeAccount"] = 4002] = "InsufficientFundsOrFreeAccount";
49
+ RealtimeErrorType[RealtimeErrorType["NonexistentSessionId"] = 4004] = "NonexistentSessionId";
50
+ RealtimeErrorType[RealtimeErrorType["SessionExpired"] = 4008] = "SessionExpired";
51
+ RealtimeErrorType[RealtimeErrorType["ClosedSession"] = 4010] = "ClosedSession";
52
+ RealtimeErrorType[RealtimeErrorType["RateLimited"] = 4029] = "RateLimited";
53
+ RealtimeErrorType[RealtimeErrorType["UniqueSessionViolation"] = 4030] = "UniqueSessionViolation";
54
+ RealtimeErrorType[RealtimeErrorType["SessionTimeout"] = 4031] = "SessionTimeout";
55
+ RealtimeErrorType[RealtimeErrorType["AudioTooShort"] = 4032] = "AudioTooShort";
56
+ RealtimeErrorType[RealtimeErrorType["AudioTooLong"] = 4033] = "AudioTooLong";
57
+ RealtimeErrorType[RealtimeErrorType["BadJson"] = 4100] = "BadJson";
58
+ RealtimeErrorType[RealtimeErrorType["BadSchema"] = 4101] = "BadSchema";
59
+ RealtimeErrorType[RealtimeErrorType["TooManyStreams"] = 4102] = "TooManyStreams";
60
+ RealtimeErrorType[RealtimeErrorType["Reconnected"] = 4103] = "Reconnected";
61
+ RealtimeErrorType[RealtimeErrorType["ReconnectAttemptsExhausted"] = 1013] = "ReconnectAttemptsExhausted";
62
+ })(RealtimeErrorType || (RealtimeErrorType = {}));
63
+ const RealtimeErrorMessages = {
64
+ [RealtimeErrorType.BadSampleRate]: "Sample rate must be a positive integer",
65
+ [RealtimeErrorType.AuthFailed]: "Not Authorized",
66
+ [RealtimeErrorType.InsufficientFundsOrFreeAccount]: "Insufficient funds or you are using a free account. This feature is paid-only and requires you to add a credit card. Please visit https://assemblyai.com/dashboard/ to add a credit card to your account.",
67
+ [RealtimeErrorType.NonexistentSessionId]: "Session ID does not exist",
68
+ [RealtimeErrorType.SessionExpired]: "Session has expired",
69
+ [RealtimeErrorType.ClosedSession]: "Session is closed",
70
+ [RealtimeErrorType.RateLimited]: "Rate limited",
71
+ [RealtimeErrorType.UniqueSessionViolation]: "Unique session violation",
72
+ [RealtimeErrorType.SessionTimeout]: "Session Timeout",
73
+ [RealtimeErrorType.AudioTooShort]: "Audio too short",
74
+ [RealtimeErrorType.AudioTooLong]: "Audio too long",
75
+ [RealtimeErrorType.BadJson]: "Bad JSON",
76
+ [RealtimeErrorType.BadSchema]: "Bad schema",
77
+ [RealtimeErrorType.TooManyStreams]: "Too many streams",
78
+ [RealtimeErrorType.Reconnected]: "Reconnected",
79
+ [RealtimeErrorType.ReconnectAttemptsExhausted]: "Reconnect attempts exhausted",
80
+ };
81
+ class RealtimeError extends Error {
82
+ }
83
+
84
+ const defaultRealtimeUrl = "wss://api.assemblyai.com/v2/realtime/ws";
85
+ const forceEndOfUtteranceMessage = `{"force_end_utterance":true}`;
86
+ const terminateSessionMessage = `{"terminate_session":true}`;
87
+ class RealtimeTranscriber {
88
+ constructor(params) {
89
+ var _a, _b;
90
+ this.listeners = {};
91
+ this.realtimeUrl = (_a = params.realtimeUrl) !== null && _a !== void 0 ? _a : defaultRealtimeUrl;
92
+ this.sampleRate = (_b = params.sampleRate) !== null && _b !== void 0 ? _b : 16000;
93
+ this.wordBoost = params.wordBoost;
94
+ this.encoding = params.encoding;
95
+ this.endUtteranceSilenceThreshold = params.endUtteranceSilenceThreshold;
96
+ this.disablePartialTranscripts = params.disablePartialTranscripts;
97
+ if ("token" in params && params.token)
98
+ this.token = params.token;
99
+ if ("apiKey" in params && params.apiKey)
100
+ this.apiKey = params.apiKey;
101
+ if (!(this.token || this.apiKey)) {
102
+ throw new Error("API key or temporary token is required.");
103
+ }
104
+ }
105
+ connectionUrl() {
106
+ const url = new URL(this.realtimeUrl);
107
+ if (url.protocol !== "wss:") {
108
+ throw new Error("Invalid protocol, must be wss");
109
+ }
110
+ const searchParams = new URLSearchParams();
111
+ if (this.token) {
112
+ searchParams.set("token", this.token);
113
+ }
114
+ searchParams.set("sample_rate", this.sampleRate.toString());
115
+ if (this.wordBoost && this.wordBoost.length > 0) {
116
+ searchParams.set("word_boost", JSON.stringify(this.wordBoost));
117
+ }
118
+ if (this.encoding) {
119
+ searchParams.set("encoding", this.encoding);
120
+ }
121
+ searchParams.set("enable_extra_session_information", "true");
122
+ if (this.disablePartialTranscripts) {
123
+ searchParams.set("disable_partial_transcripts", this.disablePartialTranscripts.toString());
124
+ }
125
+ url.search = searchParams.toString();
126
+ return url;
127
+ }
128
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
129
+ on(event, listener) {
130
+ this.listeners[event] = listener;
131
+ }
132
+ connect() {
133
+ return new Promise((resolve) => {
134
+ if (this.socket) {
135
+ throw new Error("Already connected");
136
+ }
137
+ const url = this.connectionUrl();
138
+ if (this.token) {
139
+ this.socket = factory(url.toString());
140
+ }
141
+ else {
142
+ this.socket = factory(url.toString(), {
143
+ headers: { Authorization: this.apiKey },
144
+ });
145
+ }
146
+ this.socket.binaryType = "arraybuffer";
147
+ this.socket.onopen = () => {
148
+ if (this.endUtteranceSilenceThreshold === undefined ||
149
+ this.endUtteranceSilenceThreshold === null) {
150
+ return;
151
+ }
152
+ this.configureEndUtteranceSilenceThreshold(this.endUtteranceSilenceThreshold);
153
+ };
154
+ this.socket.onclose = ({ code, reason }) => {
155
+ var _a, _b;
156
+ if (!reason) {
157
+ if (code in RealtimeErrorType) {
158
+ reason = RealtimeErrorMessages[code];
159
+ }
160
+ }
161
+ (_b = (_a = this.listeners).close) === null || _b === void 0 ? void 0 : _b.call(_a, code, reason);
162
+ };
163
+ this.socket.onerror = (event) => {
164
+ var _a, _b, _c, _d;
165
+ if (event.error)
166
+ (_b = (_a = this.listeners).error) === null || _b === void 0 ? void 0 : _b.call(_a, event.error);
167
+ else
168
+ (_d = (_c = this.listeners).error) === null || _d === void 0 ? void 0 : _d.call(_c, new Error(event.message));
169
+ };
170
+ this.socket.onmessage = ({ data }) => {
171
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
172
+ const message = JSON.parse(data.toString());
173
+ if ("error" in message) {
174
+ (_b = (_a = this.listeners).error) === null || _b === void 0 ? void 0 : _b.call(_a, new RealtimeError(message.error));
175
+ return;
176
+ }
177
+ switch (message.message_type) {
178
+ case "SessionBegins": {
179
+ const openObject = {
180
+ sessionId: message.session_id,
181
+ expiresAt: new Date(message.expires_at),
182
+ };
183
+ resolve(openObject);
184
+ (_d = (_c = this.listeners).open) === null || _d === void 0 ? void 0 : _d.call(_c, openObject);
185
+ break;
186
+ }
187
+ case "PartialTranscript": {
188
+ // message.created is actually a string when coming from the socket
189
+ message.created = new Date(message.created);
190
+ (_f = (_e = this.listeners).transcript) === null || _f === void 0 ? void 0 : _f.call(_e, message);
191
+ (_h = (_g = this.listeners)["transcript.partial"]) === null || _h === void 0 ? void 0 : _h.call(_g, message);
192
+ break;
193
+ }
194
+ case "FinalTranscript": {
195
+ // message.created is actually a string when coming from the socket
196
+ message.created = new Date(message.created);
197
+ (_k = (_j = this.listeners).transcript) === null || _k === void 0 ? void 0 : _k.call(_j, message);
198
+ (_m = (_l = this.listeners)["transcript.final"]) === null || _m === void 0 ? void 0 : _m.call(_l, message);
199
+ break;
200
+ }
201
+ case "SessionInformation": {
202
+ (_p = (_o = this.listeners).session_information) === null || _p === void 0 ? void 0 : _p.call(_o, message);
203
+ break;
204
+ }
205
+ case "SessionTerminated": {
206
+ (_q = this.sessionTerminatedResolve) === null || _q === void 0 ? void 0 : _q.call(this);
207
+ break;
208
+ }
209
+ }
210
+ };
211
+ });
212
+ }
213
+ sendAudio(audio) {
214
+ this.send(audio);
215
+ }
216
+ stream() {
217
+ return new WritableStream({
218
+ write: (chunk) => {
219
+ this.sendAudio(chunk);
220
+ },
221
+ });
222
+ }
223
+ /**
224
+ * Manually end an utterance
225
+ */
226
+ forceEndUtterance() {
227
+ this.send(forceEndOfUtteranceMessage);
228
+ }
229
+ /**
230
+ * Configure the threshold for how long to wait before ending an utterance. Default is 700ms.
231
+ * @param threshold - The duration of the end utterance silence threshold in milliseconds.
232
+ * This value must be an integer between 0 and 20_000.
233
+ */
234
+ configureEndUtteranceSilenceThreshold(threshold) {
235
+ this.send(`{"end_utterance_silence_threshold":${threshold}}`);
236
+ }
237
+ send(data) {
238
+ if (!this.socket || this.socket.readyState !== this.socket.OPEN) {
239
+ throw new Error("Socket is not open for communication");
240
+ }
241
+ this.socket.send(data);
242
+ }
243
+ close() {
244
+ return __awaiter(this, arguments, void 0, function* (waitForSessionTermination = true) {
245
+ var _a;
246
+ if (this.socket) {
247
+ if (this.socket.readyState === this.socket.OPEN) {
248
+ if (waitForSessionTermination) {
249
+ const sessionTerminatedPromise = new Promise((resolve) => {
250
+ this.sessionTerminatedResolve = resolve;
251
+ });
252
+ this.socket.send(terminateSessionMessage);
253
+ yield sessionTerminatedPromise;
254
+ }
255
+ else {
256
+ this.socket.send(terminateSessionMessage);
257
+ }
258
+ }
259
+ if ((_a = this.socket) === null || _a === void 0 ? void 0 : _a.removeAllListeners)
260
+ this.socket.removeAllListeners();
261
+ this.socket.close();
262
+ }
263
+ this.listeners = {};
264
+ this.socket = undefined;
265
+ });
266
+ }
267
+ }
268
+ /**
269
+ * @deprecated Use RealtimeTranscriber instead
270
+ */
271
+ class RealtimeService extends RealtimeTranscriber {
272
+ }
273
+
274
+ export { RealtimeService, RealtimeTranscriber };
@@ -5,3 +5,10 @@ export * from "./services";
5
5
  export * from "./asyncapi.generated";
6
6
  export * from "./openapi.generated";
7
7
  export * from "./deprecated";
8
+ export type UserAgentItem = {
9
+ name: string;
10
+ version: string;
11
+ };
12
+ export type UserAgent = {
13
+ [component: string]: UserAgentItem | undefined | null | false;
14
+ };
@@ -476,7 +476,7 @@ export type Entity = {
476
476
  /**
477
477
  * The type of entity for the detected entity
478
478
  */
479
- export type EntityType = "banking_information" | "blood_type" | "credit_card_cvv" | "credit_card_expiration" | "credit_card_number" | "date" | "date_of_birth" | "drivers_license" | "drug" | "email_address" | "event" | "injury" | "language" | "location" | "medical_condition" | "medical_process" | "money_amount" | "nationality" | "occupation" | "organization" | "password" | "person_age" | "person_name" | "phone_number" | "political_affiliation" | "religion" | "time" | "url" | "us_social_security_number";
479
+ export type EntityType = "account_number" | "banking_information" | "blood_type" | "credit_card_cvv" | "credit_card_expiration" | "credit_card_number" | "date" | "date_interval" | "date_of_birth" | "drivers_license" | "drug" | "duration" | "email_address" | "event" | "filename" | "gender_sexuality" | "healthcare_number" | "injury" | "ip_address" | "language" | "location" | "marital_status" | "medical_condition" | "medical_process" | "money_amount" | "nationality" | "number_sequence" | "occupation" | "organization" | "passport_number" | "password" | "person_age" | "person_name" | "phone_number" | "physical_attribute" | "political_affiliation" | "religion" | "statistics" | "time" | "url" | "us_social_security_number" | "username" | "vehicle_id" | "zodiac_sign";
480
480
  /**
481
481
  * @example
482
482
  * ```js
@@ -1,5 +1,12 @@
1
+ import { UserAgent } from "..";
1
2
  type BaseServiceParams = {
2
3
  apiKey: string;
3
4
  baseUrl?: string;
5
+ /**
6
+ * The AssemblyAI user agent to use for requests.
7
+ * The provided components will be merged into the default AssemblyAI user agent.
8
+ * If `false`, the AssemblyAI user agent will be removed.
9
+ */
10
+ userAgent?: UserAgent | false;
4
11
  };
5
12
  export type { BaseServiceParams };
@@ -0,0 +1,2 @@
1
+ import { UserAgent } from "../types";
2
+ export declare const buildUserAgent: (userAgent: UserAgent | false) => string;
@@ -0,0 +1,27 @@
1
+ # Reference types from JavaScript
2
+
3
+ Types are automatically configured in most IDEs when you import the `assemblyai` module using `require` or `import`.
4
+ However, if you're using the _assemblyai.umd.js_ or _assemblyai.umd.min.js_ script,
5
+ you need to manually reference the types.
6
+
7
+ 1. Install the `assemblyai` module locally.
8
+ 2. Create an _assemblyai.d.ts_ file with the following content.
9
+ ```typescript
10
+ import AssemblyAIModule from "assemblyai";
11
+ declare global {
12
+ const assemblyai: typeof AssemblyAIModule;
13
+ }
14
+ ```
15
+ This will import the TypeScript types from the `assemblyai` module,
16
+ and configure them as the global `assemblyai` variable.
17
+ 3. Reference the _assemblyai.d.ts_ file at the top of your script file.
18
+
19
+ ```js
20
+ /// <reference path="assemblyai.d.ts" />
21
+ const { RealtimeTranscriber } = assemblyai;
22
+ ...
23
+ ```
24
+
25
+ Your IDE will load the types specified in the `<reference />` tag.
26
+
27
+ > [!INFO] > `/// <reference />` tags only work in script files, not script-blocks, and should be at the top of the file.
package/package.json CHANGED
@@ -1,25 +1,26 @@
1
1
  {
2
2
  "name": "assemblyai",
3
- "version": "4.4.2",
3
+ "version": "4.4.4",
4
4
  "description": "The AssemblyAI JavaScript 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
5
  "engines": {
6
6
  "node": ">=18"
7
7
  },
8
8
  "exports": {
9
9
  ".": {
10
- "types": "./dist/index.d.ts",
10
+ "types": "./dist/exports/index.d.ts",
11
11
  "bun": {
12
- "types": "./dist/index.d.ts",
12
+ "types": "./dist/exports/index.d.ts",
13
13
  "default": "./dist/bun.mjs"
14
14
  },
15
15
  "deno": {
16
- "types": "./dist/index.d.ts",
16
+ "types": "./dist/exports/index.d.ts",
17
17
  "default": "./dist/deno.mjs"
18
18
  },
19
19
  "workerd": "./dist/index.mjs",
20
20
  "browser": "./dist/browser.mjs",
21
+ "react-native": "./dist/browser.mjs",
21
22
  "node": {
22
- "types": "./dist/index.d.ts",
23
+ "types": "./dist/exports/index.d.ts",
23
24
  "import": "./dist/node.mjs",
24
25
  "require": "./dist/node.cjs"
25
26
  },
@@ -27,6 +28,13 @@
27
28
  "require": "./dist/index.cjs",
28
29
  "default": "./dist/index.cjs"
29
30
  },
31
+ "./streaming": {
32
+ "types": "./dist/exports/streaming.d.ts",
33
+ "browser": "./dist/streaming.browser.mjs",
34
+ "import": "./dist/streaming.mjs",
35
+ "require": "./dist/streaming.cjs",
36
+ "default": "./dist/streaming.cjs"
37
+ },
30
38
  "./package.json": "./package.json"
31
39
  },
32
40
  "imports": {
@@ -47,6 +55,8 @@
47
55
  }
48
56
  },
49
57
  "type": "commonjs",
58
+ "react-native": "./dist/browser.mjs",
59
+ "browser": "./dist/browser.mjs",
50
60
  "main": "./dist/index.cjs",
51
61
  "require": "./dist/index.cjs",
52
62
  "module": "./dist/index.mjs",
@@ -64,11 +74,15 @@
64
74
  "scripts": {
65
75
  "build": "pnpm clean && pnpm rollup -c",
66
76
  "clean": "rimraf dist/* && rimraf temp/* && rimraf temp-docs/*",
67
- "lint": "eslint -c .eslintrc.json '{src,tests}/**/*.{js,ts}' && publint && tsc --noEmit -p tsconfig.json",
68
- "test": "pnpm run test:unit && pnpm run test:integration",
77
+ "lint": "pnpm lint:eslint && pnpm lint:tsc && pnpm lint:format && pnpm lint:publint",
78
+ "lint:eslint": "eslint -c .eslintrc.json '{src,tests}/**/*.{js,ts}'",
79
+ "lint:tsc": "tsc --noEmit -p tsconfig.json",
80
+ "lint:format": "prettier --check --no-error-on-unmatched-pattern {*,**/*}",
81
+ "lint:publint": "publint",
82
+ "test": "pnpm test:unit && pnpm test:integration",
69
83
  "test:unit": "jest --config jest.unit.config.js --testTimeout 1000",
70
84
  "test:integration": "jest --config jest.integration.config.js --testTimeout 360000",
71
- "format": "prettier '**/*' --write",
85
+ "format": "prettier --write --no-error-on-unmatched-pattern {*,**/*}",
72
86
  "generate:types": "tsx ./scripts/generate-types.ts && prettier 'src/types/*.generated.ts' --write",
73
87
  "generate:reference": "typedoc",
74
88
  "copybara:dry-run": "./copybara.sh dry_run --init-history",
@@ -97,16 +111,17 @@
97
111
  "docs"
98
112
  ],
99
113
  "devDependencies": {
100
- "@babel/preset-env": "^7.24.0",
101
- "@babel/preset-typescript": "^7.23.3",
114
+ "@babel/preset-env": "^7.24.5",
115
+ "@babel/preset-typescript": "^7.24.1",
102
116
  "@rollup/plugin-node-resolve": "^15.2.3",
117
+ "@rollup/plugin-replace": "^5.0.5",
103
118
  "@rollup/plugin-terser": "^0.4.4",
104
119
  "@rollup/plugin-typescript": "^11.1.6",
105
120
  "@types/jest": "^29.5.12",
106
- "@types/node": "^18.11.9",
121
+ "@types/node": "^18.19.32",
107
122
  "@types/websocket": "^1.0.10",
108
123
  "@types/ws": "^8.5.10",
109
- "@typescript-eslint/eslint-plugin": "^7.2.0",
124
+ "@typescript-eslint/eslint-plugin": "^7.8.0",
110
125
  "dotenv": "^16.4.5",
111
126
  "eslint": "^8.57.0",
112
127
  "eslint-plugin-tsdoc": "^0.2.17",
@@ -115,19 +130,20 @@
115
130
  "jest-fetch-mock": "^3.0.3",
116
131
  "jest-junit": "^16.0.0",
117
132
  "jest-websocket-mock": "^2.5.0",
133
+ "jsr": "^0.12.4",
118
134
  "mock-socket": "^9.3.1",
119
135
  "openapi-typescript": "^6.7.5",
120
136
  "prettier": "^3.2.5",
121
137
  "publint": "^0.2.7",
122
138
  "rimraf": "^5.0.5",
123
- "rollup": "^4.13.0",
139
+ "rollup": "^4.17.2",
124
140
  "ts-jest": "^29.1.2",
125
141
  "tslib": "^2.5.3",
126
- "typescript": "^5.4.2",
127
- "typedoc": "^0.25.12",
128
- "typedoc-plugin-extras": "^3.0.0"
142
+ "typedoc": "^0.25.13",
143
+ "typedoc-plugin-extras": "^3.0.0",
144
+ "typescript": "^5.4.5"
129
145
  },
130
146
  "dependencies": {
131
- "ws": "^8.16.0"
147
+ "ws": "^8.17.0"
132
148
  }
133
149
  }
@@ -0,0 +1,2 @@
1
+ export * from "../types";
2
+ export * from "../services";
@@ -0,0 +1,4 @@
1
+ export * from "../types/asyncapi.generated";
2
+ export * from "../types/realtime";
3
+ export * from "../types/helpers";
4
+ export * from "../services/realtime/service";
@@ -1,26 +1,45 @@
1
1
  import { BaseServiceParams } from "..";
2
2
  import { Error as JsonError } from "..";
3
+ import { buildUserAgent } from "../utils/userAgent";
3
4
 
4
5
  /**
5
6
  * Base class for services that communicate with the API.
6
7
  */
7
8
  export abstract class BaseService {
9
+ private userAgent: string | undefined;
8
10
  /**
9
11
  * Create a new service.
10
12
  * @param params - The parameters to use for the service.
11
13
  */
12
- constructor(private params: BaseServiceParams) {}
14
+ constructor(private params: BaseServiceParams) {
15
+ if (params.userAgent === false) {
16
+ this.userAgent = undefined;
17
+ } else {
18
+ this.userAgent = buildUserAgent(params.userAgent || {});
19
+ }
20
+ }
13
21
  protected async fetch(
14
22
  input: string,
15
23
  init?: RequestInit | undefined,
16
24
  ): Promise<Response> {
17
25
  init = init ?? {};
18
- init.headers = init.headers ?? {};
19
- init.headers = {
26
+ let headers = init.headers ?? {};
27
+ headers = {
20
28
  Authorization: this.params.apiKey,
21
29
  "Content-Type": "application/json",
22
30
  ...init.headers,
23
31
  };
32
+
33
+ if (this.userAgent) {
34
+ (headers as Record<string, string>)["User-Agent"] = this.userAgent;
35
+ // chromium browsers have a bug where the user agent can't be modified
36
+ if (typeof window !== "undefined" && "chrome" in window) {
37
+ (headers as Record<string, string>)["AssemblyAI-Agent"] =
38
+ this.userAgent;
39
+ }
40
+ }
41
+ init.headers = headers;
42
+
24
43
  init.cache = "no-store";
25
44
  if (!input.startsWith("http")) input = this.params.baseUrl + input;
26
45
 
@@ -38,8 +38,9 @@ class AssemblyAI {
38
38
  */
39
39
  constructor(params: BaseServiceParams) {
40
40
  params.baseUrl = params.baseUrl || defaultBaseUrl;
41
- if (params.baseUrl && params.baseUrl.endsWith("/"))
41
+ if (params.baseUrl && params.baseUrl.endsWith("/")) {
42
42
  params.baseUrl = params.baseUrl.slice(0, -1);
43
+ }
43
44
  this.files = new FileService(params);
44
45
  this.transcripts = new TranscriptService(params, this.files);
45
46
  this.lemur = new LemurService(params);
@@ -5,3 +5,12 @@ export * from "./services";
5
5
  export * from "./asyncapi.generated";
6
6
  export * from "./openapi.generated";
7
7
  export * from "./deprecated";
8
+
9
+ export type UserAgentItem = {
10
+ name: string;
11
+ version: string;
12
+ };
13
+
14
+ export type UserAgent = {
15
+ [component: string]: UserAgentItem | undefined | null | false;
16
+ };
@@ -497,35 +497,50 @@ export type Entity = {
497
497
  * The type of entity for the detected entity
498
498
  */
499
499
  export type EntityType =
500
+ | "account_number"
500
501
  | "banking_information"
501
502
  | "blood_type"
502
503
  | "credit_card_cvv"
503
504
  | "credit_card_expiration"
504
505
  | "credit_card_number"
505
506
  | "date"
507
+ | "date_interval"
506
508
  | "date_of_birth"
507
509
  | "drivers_license"
508
510
  | "drug"
511
+ | "duration"
509
512
  | "email_address"
510
513
  | "event"
514
+ | "filename"
515
+ | "gender_sexuality"
516
+ | "healthcare_number"
511
517
  | "injury"
518
+ | "ip_address"
512
519
  | "language"
513
520
  | "location"
521
+ | "marital_status"
514
522
  | "medical_condition"
515
523
  | "medical_process"
516
524
  | "money_amount"
517
525
  | "nationality"
526
+ | "number_sequence"
518
527
  | "occupation"
519
528
  | "organization"
529
+ | "passport_number"
520
530
  | "password"
521
531
  | "person_age"
522
532
  | "person_name"
523
533
  | "phone_number"
534
+ | "physical_attribute"
524
535
  | "political_affiliation"
525
536
  | "religion"
537
+ | "statistics"
526
538
  | "time"
527
539
  | "url"
528
- | "us_social_security_number";
540
+ | "us_social_security_number"
541
+ | "username"
542
+ | "vehicle_id"
543
+ | "zodiac_sign";
529
544
 
530
545
  /**
531
546
  * @example
@@ -1,6 +1,14 @@
1
+ import { UserAgent } from "..";
2
+
1
3
  type BaseServiceParams = {
2
4
  apiKey: string;
3
5
  baseUrl?: string;
6
+ /**
7
+ * The AssemblyAI user agent to use for requests.
8
+ * The provided components will be merged into the default AssemblyAI user agent.
9
+ * If `false`, the AssemblyAI user agent will be removed.
10
+ */
11
+ userAgent?: UserAgent | false;
4
12
  };
5
13
 
6
14
  export type { BaseServiceParams };
@@ -0,0 +1,51 @@
1
+ import { UserAgent } from "../types";
2
+
3
+ export const buildUserAgent = (userAgent: UserAgent | false) =>
4
+ defaultUserAgentString +
5
+ (userAgent === false
6
+ ? ""
7
+ : " AssemblyAI/1.0 (" +
8
+ Object.entries({ ...defaultUserAgent, ...userAgent })
9
+ .map(([key, item]) =>
10
+ item ? `${key}=${item.name}/${item.version}` : "",
11
+ )
12
+ .join(" ") +
13
+ ")");
14
+
15
+ let defaultUserAgentString = "";
16
+ if (typeof navigator !== "undefined" && navigator.userAgent) {
17
+ defaultUserAgentString += navigator.userAgent;
18
+ }
19
+
20
+ const defaultUserAgent: UserAgent = {
21
+ sdk: { name: "JavaScript", version: "__SDK_VERSION__" },
22
+ };
23
+
24
+ if (typeof process !== "undefined") {
25
+ if (process.versions.node && defaultUserAgentString.indexOf("Node") === -1) {
26
+ defaultUserAgent.runtime_env = {
27
+ name: "Node",
28
+ version: process.versions.node,
29
+ };
30
+ }
31
+ if (process.versions.bun && defaultUserAgentString.indexOf("Bun") === -1) {
32
+ defaultUserAgent.runtime_env = {
33
+ name: "Bun",
34
+ version: process.versions.bun,
35
+ };
36
+ }
37
+ }
38
+
39
+ declare const Deno:
40
+ | {
41
+ version: {
42
+ deno: string;
43
+ };
44
+ }
45
+ | undefined;
46
+
47
+ if (typeof Deno !== "undefined") {
48
+ if (process.versions.bun && defaultUserAgentString.indexOf("Deno") === -1) {
49
+ defaultUserAgent.runtime_env = { name: "Deno", version: Deno.version.deno };
50
+ }
51
+ }