@voiceinput/deepgram 0.1.0-beta.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/LICENSE +21 -0
- package/README.md +124 -0
- package/dist/index.cjs +427 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +22 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +425 -0
- package/dist/index.js.map +1 -0
- package/dist/server.cjs +167 -0
- package/dist/server.cjs.map +1 -0
- package/dist/server.d.cts +36 -0
- package/dist/server.d.cts.map +1 -0
- package/dist/server.d.ts +36 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +166 -0
- package/dist/server.js.map +1 -0
- package/dist/session-config-JCvVU8gI.js +104 -0
- package/dist/session-config-JCvVU8gI.js.map +1 -0
- package/dist/session-config-aoO2eGMT.cjs +127 -0
- package/dist/session-config-aoO2eGMT.cjs.map +1 -0
- package/package.json +77 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Hirad Arshadiyarahmadi
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# `@voiceinput/deepgram`
|
|
2
|
+
|
|
3
|
+
Deepgram live transcription adapter for VoiceInput. The browser-safe root opens
|
|
4
|
+
the realtime stream; `@voiceinput/deepgram/server` exchanges a long-lived API
|
|
5
|
+
key for a temporary JWT.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @voiceinput/react@next @voiceinput/deepgram@next
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Browser adapter
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import { deepgram } from "@voiceinput/deepgram";
|
|
17
|
+
|
|
18
|
+
const provider = deepgram({
|
|
19
|
+
tokenEndpoint: "/api/voice-token",
|
|
20
|
+
smartFormat: true,
|
|
21
|
+
punctuate: true,
|
|
22
|
+
});
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### Defaults and shared-option mapping
|
|
26
|
+
|
|
27
|
+
- Model: `nova-3` (`DEEPGRAM_DEFAULT_MODEL`)
|
|
28
|
+
- Audio: mono linear PCM16 at 16 kHz
|
|
29
|
+
- Omitted language: `multi` for `nova-2`, `nova-2-general`, `nova-3`, and
|
|
30
|
+
`nova-3-general`; other models require an explicit BCP 47 language
|
|
31
|
+
- General Nova-2 and Nova-3 preserve supported regional English tags and
|
|
32
|
+
normalize unsupported tags such as `en-CA` to `en`; specialized models keep
|
|
33
|
+
their regional language tags exact
|
|
34
|
+
- `vocabulary`: Deepgram key terms, supported only by Nova-3 model IDs
|
|
35
|
+
- `endpointing`: provider default when omitted, disabled when `false`, or the
|
|
36
|
+
supplied positive integer silence threshold
|
|
37
|
+
- `smartFormat` and `punctuate`: both default to `true`
|
|
38
|
+
|
|
39
|
+
Invalid or unsupported settings fail before microphone permission with distinct
|
|
40
|
+
error codes.
|
|
41
|
+
|
|
42
|
+
### `DeepgramVoiceInputProviderOptions`
|
|
43
|
+
|
|
44
|
+
| Option | Purpose |
|
|
45
|
+
| ----------------------------------- | ---------------------------------------------------------- |
|
|
46
|
+
| `tokenEndpoint` | Required same-origin endpoint that returns a temporary JWT |
|
|
47
|
+
| `model` | Model ID; default `nova-3` |
|
|
48
|
+
| `smartFormat` | Deepgram smart formatting; default `true` |
|
|
49
|
+
| `punctuate` | Punctuation; default `true` |
|
|
50
|
+
| `profanityFilter` | Provider profanity filter |
|
|
51
|
+
| `numerals` | Provider numeral conversion |
|
|
52
|
+
| `fetch`, `webSocket`, `realtimeUrl` | Transport/endpoint overrides |
|
|
53
|
+
|
|
54
|
+
## Server token handler
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
import { createDeepgramTokenHandler } from "@voiceinput/deepgram/server";
|
|
58
|
+
|
|
59
|
+
export const POST = createDeepgramTokenHandler({
|
|
60
|
+
apiKey: process.env.DEEPGRAM_API_KEY!,
|
|
61
|
+
ttlSeconds: 30,
|
|
62
|
+
authorize: async (request) => {
|
|
63
|
+
const user = await authenticate(request);
|
|
64
|
+
return user ? { subject: user.id } : null;
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
The handler accepts only `POST`, requires authorization, sets
|
|
70
|
+
`Cache-Control: no-store`, and returns a temporary token rather than the API
|
|
71
|
+
key. Requests must be JSON and are limited to 16 KiB. Authorization and
|
|
72
|
+
rate-limit callbacks receive independent request bodies. If `onTokenIssued`
|
|
73
|
+
throws, token delivery fails closed.
|
|
74
|
+
|
|
75
|
+
The default `ttlSeconds` is 30; overrides must be integers from 1 to 3600. Use
|
|
76
|
+
the shortest practical lifetime—the token only needs to remain valid for the
|
|
77
|
+
WebSocket handshake. Deepgram grant tokens carry `usage::write` across core
|
|
78
|
+
voice APIs rather than a speech-to-text-only scope. Isolate the backing Member
|
|
79
|
+
key in a dedicated project, apply project spending controls, and use separate
|
|
80
|
+
projects/keys for production and testing. See Deepgram's official
|
|
81
|
+
[token grant](https://developers.deepgram.com/reference/auth/tokens/grant) and
|
|
82
|
+
[authentication guide](https://developers.deepgram.com/guides/fundamentals/token-based-authentication).
|
|
83
|
+
|
|
84
|
+
### `CreateDeepgramTokenHandlerOptions`
|
|
85
|
+
|
|
86
|
+
| Option | Purpose |
|
|
87
|
+
| ------------------------- | --------------------------------------------------------------- |
|
|
88
|
+
| `apiKey` | Required server-only Deepgram key |
|
|
89
|
+
| `authorize(request)` | Required application authorization |
|
|
90
|
+
| `model` | Default model; default `nova-3` |
|
|
91
|
+
| `allowedModels` | Browser-selectable models; defaults to only `model` |
|
|
92
|
+
| `ttlSeconds` | Temporary-token lifetime, default 30; 1–3600 seconds |
|
|
93
|
+
| `rateLimit(context)` | Optional application quota check |
|
|
94
|
+
| `onTokenIssued(metadata)` | Metadata-only callback with subject, model, and expiry duration |
|
|
95
|
+
| `fetch`, `grantUrl` | Transport/endpoint overrides |
|
|
96
|
+
|
|
97
|
+
`DeepgramTokenHandlerContext` contains `request`, `subject`, and `model`.
|
|
98
|
+
`DeepgramTokenIssuedMetadata` also contains `expiresIn`.
|
|
99
|
+
|
|
100
|
+
## Public API
|
|
101
|
+
|
|
102
|
+
Browser root:
|
|
103
|
+
|
|
104
|
+
- `deepgram(options)`
|
|
105
|
+
- `DEEPGRAM_DEFAULT_MODEL`
|
|
106
|
+
- `DeepgramVoiceInputProviderOptions`
|
|
107
|
+
|
|
108
|
+
Server-only entry point:
|
|
109
|
+
|
|
110
|
+
- `createDeepgramTokenHandler(options)`
|
|
111
|
+
- `CreateDeepgramTokenHandlerOptions`
|
|
112
|
+
- `DeepgramAuthorization`
|
|
113
|
+
- `DeepgramRateLimitResult`
|
|
114
|
+
- `DeepgramTokenHandlerContext`
|
|
115
|
+
- `DeepgramTokenIssuedMetadata`
|
|
116
|
+
|
|
117
|
+
## Security
|
|
118
|
+
|
|
119
|
+
Import `/server` only from server code; the export is disabled under the browser
|
|
120
|
+
condition. Never expose `DEEPGRAM_API_KEY` to the client. The browser uses the
|
|
121
|
+
temporary JWT to stream audio directly to Deepgram.
|
|
122
|
+
|
|
123
|
+
See the
|
|
124
|
+
[secure integration guides](https://github.com/VoiceInput/voiceinput/blob/main/docs/vite-hono.md).
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,427 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_session_config = require("./session-config-aoO2eGMT.cjs");
|
|
3
|
+
let _voiceinput_provider_transport = require("@voiceinput/provider/transport");
|
|
4
|
+
let _voiceinput_provider = require("@voiceinput/provider");
|
|
5
|
+
//#region src/index.ts
|
|
6
|
+
const DEFAULT_REALTIME_URL = "wss://api.deepgram.com/v1/listen";
|
|
7
|
+
function deepgram(options) {
|
|
8
|
+
const model = factoryString(options.model ?? "nova-3", "model");
|
|
9
|
+
const tokenEndpoint = factoryString(String(options.tokenEndpoint), "tokenEndpoint");
|
|
10
|
+
const realtimeUrl = factoryString(options.realtimeUrl ?? DEFAULT_REALTIME_URL, "realtimeUrl");
|
|
11
|
+
const providerSettings = {
|
|
12
|
+
...options.smartFormat === void 0 ? {} : { smartFormat: options.smartFormat },
|
|
13
|
+
...options.punctuate === void 0 ? {} : { punctuate: options.punctuate },
|
|
14
|
+
...options.profanityFilter === void 0 ? {} : { profanityFilter: options.profanityFilter },
|
|
15
|
+
...options.numerals === void 0 ? {} : { numerals: options.numerals }
|
|
16
|
+
};
|
|
17
|
+
const validateProviderOptions = (transcriptionOptions) => {
|
|
18
|
+
try {
|
|
19
|
+
require_session_config.validateDeepgramConfiguration({
|
|
20
|
+
model,
|
|
21
|
+
...providerSettings,
|
|
22
|
+
...transcriptionOptions
|
|
23
|
+
});
|
|
24
|
+
} catch (cause) {
|
|
25
|
+
if (_voiceinput_provider.VoiceInputError.isInstance(cause)) throw cause;
|
|
26
|
+
throw invalidConfiguration(cause);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
return Object.freeze({
|
|
30
|
+
specificationVersion: "v1",
|
|
31
|
+
provider: "deepgram",
|
|
32
|
+
modelId: model,
|
|
33
|
+
sampleRate: require_session_config.DEEPGRAM_SAMPLE_RATE,
|
|
34
|
+
validateOptions: validateProviderOptions,
|
|
35
|
+
async doOpen(callOptions) {
|
|
36
|
+
validateProviderOptions(callOptions);
|
|
37
|
+
const configuration = require_session_config.validateDeepgramConfiguration({
|
|
38
|
+
model,
|
|
39
|
+
...providerSettings,
|
|
40
|
+
...callOptions
|
|
41
|
+
});
|
|
42
|
+
return await openSession({
|
|
43
|
+
abortSignal: callOptions.abortSignal,
|
|
44
|
+
configuration,
|
|
45
|
+
fetchImplementation: options.fetch ?? globalThis.fetch,
|
|
46
|
+
realtimeUrl,
|
|
47
|
+
tokenEndpoint,
|
|
48
|
+
WebSocketImplementation: options.webSocket ?? globalThis.WebSocket
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
async function openSession(options) {
|
|
54
|
+
throwIfAborted(options.abortSignal);
|
|
55
|
+
requireBrowserFunction(options.fetchImplementation, "fetch");
|
|
56
|
+
requireBrowserFunction(options.WebSocketImplementation, "WebSocket");
|
|
57
|
+
const token = await requestToken(options.fetchImplementation, options.tokenEndpoint, options.configuration.model, options.abortSignal);
|
|
58
|
+
throwIfAborted(options.abortSignal);
|
|
59
|
+
return await createSession(new options.WebSocketImplementation(require_session_config.createDeepgramRealtimeUrl(options.realtimeUrl, options.configuration), ["bearer", token]), options.abortSignal);
|
|
60
|
+
}
|
|
61
|
+
async function requestToken(fetchImplementation, tokenEndpoint, model, abortSignal) {
|
|
62
|
+
let response;
|
|
63
|
+
try {
|
|
64
|
+
response = await fetchImplementation(tokenEndpoint, {
|
|
65
|
+
method: "POST",
|
|
66
|
+
headers: { "Content-Type": "application/json" },
|
|
67
|
+
body: JSON.stringify({ model }),
|
|
68
|
+
credentials: "same-origin",
|
|
69
|
+
signal: abortSignal
|
|
70
|
+
});
|
|
71
|
+
} catch (cause) {
|
|
72
|
+
throwIfAborted(abortSignal);
|
|
73
|
+
throw new _voiceinput_provider.VoiceInputError({
|
|
74
|
+
code: "network-error",
|
|
75
|
+
message: "Unable to reach the Deepgram token endpoint.",
|
|
76
|
+
provider: "deepgram",
|
|
77
|
+
retryable: true,
|
|
78
|
+
cause
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
if (!response.ok) throw await tokenResponseError(response);
|
|
82
|
+
let value;
|
|
83
|
+
try {
|
|
84
|
+
value = await response.json();
|
|
85
|
+
} catch (cause) {
|
|
86
|
+
throw new _voiceinput_provider.VoiceInputError({
|
|
87
|
+
code: "token-error",
|
|
88
|
+
message: "The Deepgram token endpoint returned invalid JSON.",
|
|
89
|
+
provider: "deepgram",
|
|
90
|
+
cause
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
if (!isRecord(value) || !nonEmpty(value["access_token"])) throw new _voiceinput_provider.VoiceInputError({
|
|
94
|
+
code: "token-error",
|
|
95
|
+
message: "The Deepgram token endpoint returned an invalid token.",
|
|
96
|
+
provider: "deepgram"
|
|
97
|
+
});
|
|
98
|
+
return value["access_token"];
|
|
99
|
+
}
|
|
100
|
+
async function createSession(socket, abortSignal) {
|
|
101
|
+
let controller;
|
|
102
|
+
const stream = new ReadableStream({ start(value) {
|
|
103
|
+
controller = value;
|
|
104
|
+
} });
|
|
105
|
+
if (controller === void 0) throw new _voiceinput_provider.VoiceInputError({
|
|
106
|
+
code: "provider-error",
|
|
107
|
+
message: "Unable to initialize the Deepgram transcript stream.",
|
|
108
|
+
provider: "deepgram"
|
|
109
|
+
});
|
|
110
|
+
let audioSent = false;
|
|
111
|
+
let closed = false;
|
|
112
|
+
let failed = false;
|
|
113
|
+
let finishing = false;
|
|
114
|
+
const closedSegments = /* @__PURE__ */ new Set();
|
|
115
|
+
let lastInterim = "";
|
|
116
|
+
let speechActive = false;
|
|
117
|
+
const closeSocket = (reason) => {
|
|
118
|
+
if (socket.readyState === 0 || socket.readyState === 1) socket.close(1e3, reason);
|
|
119
|
+
};
|
|
120
|
+
const closeStream = () => {
|
|
121
|
+
if (closed) return;
|
|
122
|
+
closed = true;
|
|
123
|
+
abortSignal.removeEventListener("abort", abort);
|
|
124
|
+
controller?.close();
|
|
125
|
+
};
|
|
126
|
+
const finishCleanly = () => {
|
|
127
|
+
closeStream();
|
|
128
|
+
closeSocket("finished");
|
|
129
|
+
};
|
|
130
|
+
const fail = (error) => {
|
|
131
|
+
if (closed || failed) return;
|
|
132
|
+
failed = true;
|
|
133
|
+
controller?.enqueue({
|
|
134
|
+
type: "error",
|
|
135
|
+
error
|
|
136
|
+
});
|
|
137
|
+
closeStream();
|
|
138
|
+
closeSocket("aborted");
|
|
139
|
+
};
|
|
140
|
+
const startSpeech = () => {
|
|
141
|
+
if (!speechActive) {
|
|
142
|
+
speechActive = true;
|
|
143
|
+
controller?.enqueue({ type: "speech-start" });
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
const endSpeech = () => {
|
|
147
|
+
if (speechActive) {
|
|
148
|
+
speechActive = false;
|
|
149
|
+
controller?.enqueue({ type: "speech-end" });
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
const handleResults = (value) => {
|
|
153
|
+
const channel = value["channel"];
|
|
154
|
+
if (!isRecord(channel) || !Array.isArray(channel["alternatives"])) throw new TypeError("Deepgram Results did not contain alternatives.");
|
|
155
|
+
const alternative = channel["alternatives"][0];
|
|
156
|
+
if (!isRecord(alternative) || typeof alternative["transcript"] !== "string") throw new TypeError("Deepgram Results did not contain a transcript.");
|
|
157
|
+
const text = alternative["transcript"];
|
|
158
|
+
const isFinal = value["is_final"] === true;
|
|
159
|
+
const start = value["start"];
|
|
160
|
+
if (typeof start !== "number" || !Number.isFinite(start) || start < 0) throw new TypeError("Deepgram Results did not contain an audio start boundary.");
|
|
161
|
+
const segmentId = `audio:${start}`;
|
|
162
|
+
if (closedSegments.has(segmentId)) return;
|
|
163
|
+
if (text.length > 0 || isFinal) {
|
|
164
|
+
if (text.length > 0) startSpeech();
|
|
165
|
+
if (isFinal) {
|
|
166
|
+
closedSegments.add(segmentId);
|
|
167
|
+
controller?.enqueue({
|
|
168
|
+
type: "final",
|
|
169
|
+
text,
|
|
170
|
+
segmentId
|
|
171
|
+
});
|
|
172
|
+
lastInterim = "";
|
|
173
|
+
} else if (text !== lastInterim) {
|
|
174
|
+
lastInterim = text;
|
|
175
|
+
controller?.enqueue({
|
|
176
|
+
type: "interim",
|
|
177
|
+
text,
|
|
178
|
+
segmentId
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
if (value["speech_final"] === true) endSpeech();
|
|
183
|
+
};
|
|
184
|
+
const handleMessage = (event) => {
|
|
185
|
+
if (closed) return;
|
|
186
|
+
try {
|
|
187
|
+
const value = JSON.parse(String(event.data));
|
|
188
|
+
if (!isRecord(value) || !nonEmpty(value["type"])) throw new TypeError("Deepgram sent an invalid streaming event.");
|
|
189
|
+
const type = value["type"];
|
|
190
|
+
if (type === "Results") handleResults(value);
|
|
191
|
+
else if (type === "SpeechStarted") startSpeech();
|
|
192
|
+
else if (type === "UtteranceEnd") endSpeech();
|
|
193
|
+
else if (type === "Error") fail(normalizeMessageError(value));
|
|
194
|
+
} catch (cause) {
|
|
195
|
+
fail(new _voiceinput_provider.VoiceInputError({
|
|
196
|
+
code: "provider-error",
|
|
197
|
+
message: "Deepgram sent an invalid streaming event.",
|
|
198
|
+
provider: "deepgram",
|
|
199
|
+
cause
|
|
200
|
+
}));
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
const handleClose = (event) => {
|
|
204
|
+
if (closed) return;
|
|
205
|
+
if (event.code === 1e3) closeStream();
|
|
206
|
+
else fail(normalizeCloseError(event));
|
|
207
|
+
};
|
|
208
|
+
function abort() {
|
|
209
|
+
if (closed) return;
|
|
210
|
+
closeStream();
|
|
211
|
+
closeSocket("aborted");
|
|
212
|
+
}
|
|
213
|
+
socket.addEventListener("message", handleMessage);
|
|
214
|
+
socket.addEventListener("close", handleClose);
|
|
215
|
+
socket.addEventListener("error", () => {
|
|
216
|
+
fail(new _voiceinput_provider.VoiceInputError({
|
|
217
|
+
code: "network-error",
|
|
218
|
+
message: "The Deepgram streaming connection failed.",
|
|
219
|
+
provider: "deepgram",
|
|
220
|
+
retryable: true
|
|
221
|
+
}));
|
|
222
|
+
});
|
|
223
|
+
abortSignal.addEventListener("abort", abort, { once: true });
|
|
224
|
+
await waitForOpen(socket, abortSignal);
|
|
225
|
+
return {
|
|
226
|
+
stream,
|
|
227
|
+
sendAudio(chunk) {
|
|
228
|
+
if (closed || finishing || chunk.length === 0) return;
|
|
229
|
+
audioSent = true;
|
|
230
|
+
try {
|
|
231
|
+
return (0, _voiceinput_provider_transport.sendWithBackpressure)(socket, chunk.byteLength, abortSignal, "deepgram", () => socket.send(new Int16Array(chunk).buffer));
|
|
232
|
+
} catch (cause) {
|
|
233
|
+
throw new _voiceinput_provider.VoiceInputError({
|
|
234
|
+
code: "network-error",
|
|
235
|
+
message: "Unable to send audio to Deepgram.",
|
|
236
|
+
provider: "deepgram",
|
|
237
|
+
retryable: true,
|
|
238
|
+
cause
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
},
|
|
242
|
+
finish() {
|
|
243
|
+
if (closed || finishing) return;
|
|
244
|
+
finishing = true;
|
|
245
|
+
if (!audioSent) {
|
|
246
|
+
finishCleanly();
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
sendJson(socket, { type: "CloseStream" });
|
|
250
|
+
},
|
|
251
|
+
abort
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
function normalizeMessageError(value) {
|
|
255
|
+
const code = typeof value["code"] === "string" ? value["code"] : "";
|
|
256
|
+
const description = typeof value["description"] === "string" ? value["description"] : typeof value["message"] === "string" ? value["message"] : "";
|
|
257
|
+
const source = `${code} ${description}`;
|
|
258
|
+
const rateLimited = /rate|quota|429/iu.test(source);
|
|
259
|
+
const unauthorized = /auth|unauthorized|401|403/iu.test(source);
|
|
260
|
+
return new _voiceinput_provider.VoiceInputError({
|
|
261
|
+
code: unauthorized ? "unauthorized" : rateLimited ? "rate-limited" : "provider-error",
|
|
262
|
+
message: description || "Deepgram reported a streaming error.",
|
|
263
|
+
provider: "deepgram",
|
|
264
|
+
retryable: rateLimited || /internal|unavailable/iu.test(source),
|
|
265
|
+
cause: value
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
function normalizeCloseError(event) {
|
|
269
|
+
const reason = event.reason ?? "";
|
|
270
|
+
const rateLimited = event.code === 1013 || /rate|quota|429/iu.test(reason);
|
|
271
|
+
const unauthorized = /auth|unauthorized|401|403/iu.test(reason);
|
|
272
|
+
const invalidAudio = event.code === 1008 && /data|audio|decode/iu.test(reason);
|
|
273
|
+
return new _voiceinput_provider.VoiceInputError({
|
|
274
|
+
code: unauthorized ? "unauthorized" : rateLimited ? "rate-limited" : invalidAudio ? "audio-error" : "network-error",
|
|
275
|
+
message: "The Deepgram streaming connection closed unexpectedly.",
|
|
276
|
+
provider: "deepgram",
|
|
277
|
+
retryable: rateLimited || !unauthorized && !invalidAudio,
|
|
278
|
+
cause: event
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
function invalidConfiguration(cause) {
|
|
282
|
+
return new _voiceinput_provider.VoiceInputError({
|
|
283
|
+
code: "invalid-configuration",
|
|
284
|
+
message: cause instanceof Error ? cause.message : "Invalid Deepgram transcription options.",
|
|
285
|
+
provider: "deepgram",
|
|
286
|
+
cause
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
function requireBrowserFunction(value, feature) {
|
|
290
|
+
if (typeof value !== "function") throw new _voiceinput_provider.VoiceInputError({
|
|
291
|
+
code: "unsupported-browser",
|
|
292
|
+
message: `Deepgram voice input requires browser ${feature} support.`,
|
|
293
|
+
provider: "deepgram"
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
function factoryString(value, name) {
|
|
297
|
+
if (value.trim().length === 0) throw invalidConfiguration(/* @__PURE__ */ new TypeError(`${name} must be non-empty.`));
|
|
298
|
+
return value;
|
|
299
|
+
}
|
|
300
|
+
async function tokenResponseError(response) {
|
|
301
|
+
const retryAfterMs = parseRetryAfter(response.headers.get("Retry-After"));
|
|
302
|
+
if (response.status === 401 || response.status === 403) return new _voiceinput_provider.VoiceInputError({
|
|
303
|
+
code: "unauthorized",
|
|
304
|
+
message: "The Deepgram token endpoint rejected this request.",
|
|
305
|
+
provider: "deepgram"
|
|
306
|
+
});
|
|
307
|
+
if (response.status === 429) return new _voiceinput_provider.VoiceInputError({
|
|
308
|
+
code: "rate-limited",
|
|
309
|
+
message: "The Deepgram token endpoint rate limit was exceeded.",
|
|
310
|
+
provider: "deepgram",
|
|
311
|
+
retryable: true,
|
|
312
|
+
...retryAfterMs === void 0 ? {} : { retryAfterMs }
|
|
313
|
+
});
|
|
314
|
+
const safeError = await readSafeTokenError(response);
|
|
315
|
+
if (safeError !== void 0) return new _voiceinput_provider.VoiceInputError({
|
|
316
|
+
...safeError,
|
|
317
|
+
provider: "deepgram"
|
|
318
|
+
});
|
|
319
|
+
return new _voiceinput_provider.VoiceInputError({
|
|
320
|
+
code: "token-error",
|
|
321
|
+
message: "The Deepgram token endpoint did not issue a token.",
|
|
322
|
+
provider: "deepgram",
|
|
323
|
+
retryable: response.status >= 500
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
async function readSafeTokenError(response) {
|
|
327
|
+
if (response.status !== 400 || response.headers.get("X-VoiceInput-Error") !== "1" || response.headers.get("Content-Type")?.split(";", 1)[0]?.trim() !== "application/json") return;
|
|
328
|
+
const text = await readBoundedErrorText(response);
|
|
329
|
+
if (text === void 0) return void 0;
|
|
330
|
+
try {
|
|
331
|
+
const value = JSON.parse(text);
|
|
332
|
+
const error = isRecord(value) ? value["error"] : void 0;
|
|
333
|
+
if (!isRecord(error) || error["code"] !== "invalid-configuration" && error["code"] !== "unsupported-feature" || typeof error["message"] !== "string" || error["message"].length === 0 || error["message"].length > 1e3) return;
|
|
334
|
+
return {
|
|
335
|
+
code: error["code"],
|
|
336
|
+
message: error["message"]
|
|
337
|
+
};
|
|
338
|
+
} catch {
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
async function readBoundedErrorText(response) {
|
|
343
|
+
const reader = response.body?.getReader();
|
|
344
|
+
if (reader === void 0) return void 0;
|
|
345
|
+
const decoder = new TextDecoder();
|
|
346
|
+
let bytesRead = 0;
|
|
347
|
+
let text = "";
|
|
348
|
+
try {
|
|
349
|
+
while (true) {
|
|
350
|
+
const { done, value } = await reader.read();
|
|
351
|
+
if (done) return text + decoder.decode();
|
|
352
|
+
bytesRead += value.byteLength;
|
|
353
|
+
if (bytesRead > 4096) {
|
|
354
|
+
await reader.cancel().catch(() => {});
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
text += decoder.decode(value, { stream: true });
|
|
358
|
+
}
|
|
359
|
+
} catch {
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
function waitForOpen(socket, abortSignal) {
|
|
364
|
+
if (socket.readyState === 1) return Promise.resolve();
|
|
365
|
+
return new Promise((resolve, reject) => {
|
|
366
|
+
const cleanup = () => {
|
|
367
|
+
socket.removeEventListener("open", handleOpen);
|
|
368
|
+
socket.removeEventListener("error", handleError);
|
|
369
|
+
abortSignal.removeEventListener("abort", handleAbort);
|
|
370
|
+
};
|
|
371
|
+
const handleOpen = () => {
|
|
372
|
+
cleanup();
|
|
373
|
+
resolve();
|
|
374
|
+
};
|
|
375
|
+
const handleError = (event) => {
|
|
376
|
+
cleanup();
|
|
377
|
+
reject(new _voiceinput_provider.VoiceInputError({
|
|
378
|
+
code: "network-error",
|
|
379
|
+
message: "Unable to open the Deepgram streaming connection.",
|
|
380
|
+
provider: "deepgram",
|
|
381
|
+
retryable: true,
|
|
382
|
+
cause: event
|
|
383
|
+
}));
|
|
384
|
+
};
|
|
385
|
+
const handleAbort = () => {
|
|
386
|
+
cleanup();
|
|
387
|
+
reject(abortSignal.reason);
|
|
388
|
+
};
|
|
389
|
+
socket.addEventListener("open", handleOpen, { once: true });
|
|
390
|
+
socket.addEventListener("error", handleError, { once: true });
|
|
391
|
+
abortSignal.addEventListener("abort", handleAbort, { once: true });
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
function sendJson(socket, value) {
|
|
395
|
+
try {
|
|
396
|
+
socket.send(JSON.stringify(value));
|
|
397
|
+
} catch (cause) {
|
|
398
|
+
throw new _voiceinput_provider.VoiceInputError({
|
|
399
|
+
code: "network-error",
|
|
400
|
+
message: "Unable to send data to Deepgram.",
|
|
401
|
+
provider: "deepgram",
|
|
402
|
+
retryable: true,
|
|
403
|
+
cause
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
function parseRetryAfter(value) {
|
|
408
|
+
if (value === null) return;
|
|
409
|
+
const seconds = Number(value);
|
|
410
|
+
if (Number.isFinite(seconds) && seconds >= 0) return Math.ceil(seconds * 1e3);
|
|
411
|
+
const date = Date.parse(value);
|
|
412
|
+
return Number.isNaN(date) ? void 0 : Math.max(0, date - Date.now());
|
|
413
|
+
}
|
|
414
|
+
function throwIfAborted(signal) {
|
|
415
|
+
if (signal.aborted) throw signal.reason;
|
|
416
|
+
}
|
|
417
|
+
function nonEmpty(value) {
|
|
418
|
+
return typeof value === "string" && value.length > 0;
|
|
419
|
+
}
|
|
420
|
+
function isRecord(value) {
|
|
421
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
422
|
+
}
|
|
423
|
+
//#endregion
|
|
424
|
+
exports.DEEPGRAM_DEFAULT_MODEL = require_session_config.DEEPGRAM_DEFAULT_MODEL;
|
|
425
|
+
exports.deepgram = deepgram;
|
|
426
|
+
|
|
427
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["VoiceInputError","DEEPGRAM_SAMPLE_RATE","validateDeepgramConfiguration","createDeepgramRealtimeUrl","sendWithBackpressure"],"sources":["../src/index.ts"],"sourcesContent":["import { sendWithBackpressure } from \"@voiceinput/provider/transport\";\nimport {\n VoiceInputError,\n type VoiceInputProviderV1,\n type VoiceInputProviderV1CallOptions,\n type VoiceInputProviderV1Session,\n type VoiceInputProviderV1StreamPart,\n type VoiceTranscriptionOptions,\n} from \"@voiceinput/provider\";\n\nimport {\n DEEPGRAM_DEFAULT_MODEL,\n DEEPGRAM_SAMPLE_RATE,\n createDeepgramRealtimeUrl,\n validateDeepgramConfiguration,\n type DeepgramRealtimeSettings,\n type DeepgramSessionConfiguration,\n} from \"./session-config.js\";\n\nconst DEFAULT_REALTIME_URL = \"wss://api.deepgram.com/v1/listen\";\n\nexport interface DeepgramVoiceInputProviderOptions extends DeepgramRealtimeSettings {\n readonly tokenEndpoint: string | URL;\n readonly model?: string;\n readonly fetch?: typeof globalThis.fetch;\n readonly webSocket?: typeof globalThis.WebSocket;\n readonly realtimeUrl?: string;\n}\n\nexport function deepgram(\n options: DeepgramVoiceInputProviderOptions,\n): VoiceInputProviderV1 {\n const model = factoryString(options.model ?? DEEPGRAM_DEFAULT_MODEL, \"model\");\n const tokenEndpoint = factoryString(\n String(options.tokenEndpoint),\n \"tokenEndpoint\",\n );\n const realtimeUrl = factoryString(\n options.realtimeUrl ?? DEFAULT_REALTIME_URL,\n \"realtimeUrl\",\n );\n const providerSettings: DeepgramRealtimeSettings = {\n ...(options.smartFormat === undefined\n ? {}\n : { smartFormat: options.smartFormat }),\n ...(options.punctuate === undefined\n ? {}\n : { punctuate: options.punctuate }),\n ...(options.profanityFilter === undefined\n ? {}\n : { profanityFilter: options.profanityFilter }),\n ...(options.numerals === undefined ? {} : { numerals: options.numerals }),\n };\n const validateProviderOptions = (\n transcriptionOptions: VoiceTranscriptionOptions,\n ): void => {\n try {\n validateDeepgramConfiguration({\n model,\n ...providerSettings,\n ...transcriptionOptions,\n });\n } catch (cause) {\n if (VoiceInputError.isInstance(cause)) {\n throw cause;\n }\n throw invalidConfiguration(cause);\n }\n };\n\n return Object.freeze({\n specificationVersion: \"v1\" as const,\n provider: \"deepgram\",\n modelId: model,\n sampleRate: DEEPGRAM_SAMPLE_RATE,\n validateOptions: validateProviderOptions,\n async doOpen(callOptions: VoiceInputProviderV1CallOptions) {\n validateProviderOptions(callOptions);\n const configuration = validateDeepgramConfiguration({\n model,\n ...providerSettings,\n ...callOptions,\n });\n return await openSession({\n abortSignal: callOptions.abortSignal,\n configuration,\n fetchImplementation: options.fetch ?? globalThis.fetch,\n realtimeUrl,\n tokenEndpoint,\n WebSocketImplementation: options.webSocket ?? globalThis.WebSocket,\n });\n },\n });\n}\n\nasync function openSession(options: {\n abortSignal: AbortSignal;\n configuration: DeepgramSessionConfiguration;\n fetchImplementation: typeof globalThis.fetch;\n realtimeUrl: string;\n tokenEndpoint: string;\n WebSocketImplementation: typeof globalThis.WebSocket;\n}): Promise<VoiceInputProviderV1Session> {\n throwIfAborted(options.abortSignal);\n requireBrowserFunction(options.fetchImplementation, \"fetch\");\n requireBrowserFunction(options.WebSocketImplementation, \"WebSocket\");\n const token = await requestToken(\n options.fetchImplementation,\n options.tokenEndpoint,\n options.configuration.model,\n options.abortSignal,\n );\n throwIfAborted(options.abortSignal);\n const socket = new options.WebSocketImplementation(\n createDeepgramRealtimeUrl(options.realtimeUrl, options.configuration),\n [\"bearer\", token],\n );\n return await createSession(socket, options.abortSignal);\n}\n\nasync function requestToken(\n fetchImplementation: typeof globalThis.fetch,\n tokenEndpoint: string,\n model: string,\n abortSignal: AbortSignal,\n): Promise<string> {\n let response: Response;\n try {\n response = await fetchImplementation(tokenEndpoint, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ model }),\n credentials: \"same-origin\",\n signal: abortSignal,\n });\n } catch (cause) {\n throwIfAborted(abortSignal);\n throw new VoiceInputError({\n code: \"network-error\",\n message: \"Unable to reach the Deepgram token endpoint.\",\n provider: \"deepgram\",\n retryable: true,\n cause,\n });\n }\n if (!response.ok) {\n throw await tokenResponseError(response);\n }\n let value: unknown;\n try {\n value = await response.json();\n } catch (cause) {\n throw new VoiceInputError({\n code: \"token-error\",\n message: \"The Deepgram token endpoint returned invalid JSON.\",\n provider: \"deepgram\",\n cause,\n });\n }\n if (!isRecord(value) || !nonEmpty(value[\"access_token\"])) {\n throw new VoiceInputError({\n code: \"token-error\",\n message: \"The Deepgram token endpoint returned an invalid token.\",\n provider: \"deepgram\",\n });\n }\n return value[\"access_token\"];\n}\n\nasync function createSession(\n socket: WebSocket,\n abortSignal: AbortSignal,\n): Promise<VoiceInputProviderV1Session> {\n let controller:\n ReadableStreamDefaultController<VoiceInputProviderV1StreamPart> | undefined;\n const stream = new ReadableStream<VoiceInputProviderV1StreamPart>({\n start(value) {\n controller = value;\n },\n });\n if (controller === undefined) {\n throw new VoiceInputError({\n code: \"provider-error\",\n message: \"Unable to initialize the Deepgram transcript stream.\",\n provider: \"deepgram\",\n });\n }\n\n let audioSent = false;\n let closed = false;\n let failed = false;\n let finishing = false;\n const closedSegments = new Set<string>();\n let lastInterim = \"\";\n let speechActive = false;\n\n const closeSocket = (reason: \"aborted\" | \"finished\"): void => {\n if (socket.readyState === 0 || socket.readyState === 1) {\n socket.close(1000, reason);\n }\n };\n const closeStream = (): void => {\n if (closed) {\n return;\n }\n closed = true;\n abortSignal.removeEventListener(\"abort\", abort);\n controller?.close();\n };\n const finishCleanly = (): void => {\n closeStream();\n closeSocket(\"finished\");\n };\n const fail = (error: VoiceInputError): void => {\n if (closed || failed) {\n return;\n }\n failed = true;\n controller?.enqueue({ type: \"error\", error });\n closeStream();\n closeSocket(\"aborted\");\n };\n const startSpeech = (): void => {\n if (!speechActive) {\n speechActive = true;\n controller?.enqueue({ type: \"speech-start\" });\n }\n };\n const endSpeech = (): void => {\n if (speechActive) {\n speechActive = false;\n controller?.enqueue({ type: \"speech-end\" });\n }\n };\n const handleResults = (value: Record<string, unknown>): void => {\n const channel = value[\"channel\"];\n if (!isRecord(channel) || !Array.isArray(channel[\"alternatives\"])) {\n throw new TypeError(\"Deepgram Results did not contain alternatives.\");\n }\n const alternative = channel[\"alternatives\"][0];\n if (\n !isRecord(alternative) ||\n typeof alternative[\"transcript\"] !== \"string\"\n ) {\n throw new TypeError(\"Deepgram Results did not contain a transcript.\");\n }\n const text = alternative[\"transcript\"];\n const isFinal = value[\"is_final\"] === true;\n const start = value[\"start\"];\n if (typeof start !== \"number\" || !Number.isFinite(start) || start < 0)\n throw new TypeError(\n \"Deepgram Results did not contain an audio start boundary.\",\n );\n const segmentId = `audio:${start}`;\n if (closedSegments.has(segmentId)) return;\n if (text.length > 0 || isFinal) {\n if (text.length > 0) startSpeech();\n if (isFinal) {\n closedSegments.add(segmentId);\n controller?.enqueue({ type: \"final\", text, segmentId });\n lastInterim = \"\";\n } else if (text !== lastInterim) {\n lastInterim = text;\n controller?.enqueue({ type: \"interim\", text, segmentId });\n }\n }\n if (value[\"speech_final\"] === true) {\n endSpeech();\n }\n };\n const handleMessage = (event: MessageEvent): void => {\n if (closed) {\n return;\n }\n try {\n const value = JSON.parse(String(event.data)) as unknown;\n if (!isRecord(value) || !nonEmpty(value[\"type\"])) {\n throw new TypeError(\"Deepgram sent an invalid streaming event.\");\n }\n const type = value[\"type\"];\n if (type === \"Results\") {\n handleResults(value);\n } else if (type === \"SpeechStarted\") {\n startSpeech();\n } else if (type === \"UtteranceEnd\") {\n endSpeech();\n } else if (type === \"Error\") {\n fail(normalizeMessageError(value));\n }\n } catch (cause) {\n fail(\n new VoiceInputError({\n code: \"provider-error\",\n message: \"Deepgram sent an invalid streaming event.\",\n provider: \"deepgram\",\n cause,\n }),\n );\n }\n };\n const handleClose = (event: CloseEvent): void => {\n if (closed) {\n return;\n }\n if (event.code === 1000) {\n closeStream();\n } else {\n fail(normalizeCloseError(event));\n }\n };\n function abort(): void {\n if (closed) {\n return;\n }\n closeStream();\n closeSocket(\"aborted\");\n }\n\n socket.addEventListener(\"message\", handleMessage);\n socket.addEventListener(\"close\", handleClose);\n socket.addEventListener(\"error\", () => {\n fail(\n new VoiceInputError({\n code: \"network-error\",\n message: \"The Deepgram streaming connection failed.\",\n provider: \"deepgram\",\n retryable: true,\n }),\n );\n });\n abortSignal.addEventListener(\"abort\", abort, { once: true });\n await waitForOpen(socket, abortSignal);\n\n return {\n stream,\n sendAudio(chunk) {\n if (closed || finishing || chunk.length === 0) {\n return;\n }\n audioSent = true;\n try {\n return sendWithBackpressure(\n socket,\n chunk.byteLength,\n abortSignal,\n \"deepgram\",\n () => socket.send(new Int16Array(chunk).buffer),\n );\n } catch (cause) {\n throw new VoiceInputError({\n code: \"network-error\",\n message: \"Unable to send audio to Deepgram.\",\n provider: \"deepgram\",\n retryable: true,\n cause,\n });\n }\n },\n finish() {\n if (closed || finishing) {\n return;\n }\n finishing = true;\n if (!audioSent) {\n finishCleanly();\n return;\n }\n sendJson(socket, { type: \"CloseStream\" });\n },\n abort,\n };\n}\n\nfunction normalizeMessageError(\n value: Record<string, unknown>,\n): VoiceInputError {\n const code = typeof value[\"code\"] === \"string\" ? value[\"code\"] : \"\";\n const description =\n typeof value[\"description\"] === \"string\"\n ? value[\"description\"]\n : typeof value[\"message\"] === \"string\"\n ? value[\"message\"]\n : \"\";\n const source = `${code} ${description}`;\n const rateLimited = /rate|quota|429/iu.test(source);\n const unauthorized = /auth|unauthorized|401|403/iu.test(source);\n return new VoiceInputError({\n code: unauthorized\n ? \"unauthorized\"\n : rateLimited\n ? \"rate-limited\"\n : \"provider-error\",\n message: description || \"Deepgram reported a streaming error.\",\n provider: \"deepgram\",\n retryable: rateLimited || /internal|unavailable/iu.test(source),\n cause: value,\n });\n}\n\nfunction normalizeCloseError(event: CloseEvent): VoiceInputError {\n const reason = event.reason ?? \"\";\n const rateLimited = event.code === 1013 || /rate|quota|429/iu.test(reason);\n const unauthorized = /auth|unauthorized|401|403/iu.test(reason);\n const invalidAudio =\n event.code === 1008 && /data|audio|decode/iu.test(reason);\n return new VoiceInputError({\n code: unauthorized\n ? \"unauthorized\"\n : rateLimited\n ? \"rate-limited\"\n : invalidAudio\n ? \"audio-error\"\n : \"network-error\",\n message: \"The Deepgram streaming connection closed unexpectedly.\",\n provider: \"deepgram\",\n retryable: rateLimited || (!unauthorized && !invalidAudio),\n cause: event,\n });\n}\n\nfunction invalidConfiguration(cause: unknown): VoiceInputError {\n return new VoiceInputError({\n code: \"invalid-configuration\",\n message:\n cause instanceof Error\n ? cause.message\n : \"Invalid Deepgram transcription options.\",\n provider: \"deepgram\",\n cause,\n });\n}\n\nfunction requireBrowserFunction(value: unknown, feature: string): void {\n if (typeof value !== \"function\") {\n throw new VoiceInputError({\n code: \"unsupported-browser\",\n message: `Deepgram voice input requires browser ${feature} support.`,\n provider: \"deepgram\",\n });\n }\n}\n\nfunction factoryString(value: string, name: string): string {\n if (value.trim().length === 0) {\n throw invalidConfiguration(new TypeError(`${name} must be non-empty.`));\n }\n return value;\n}\n\nasync function tokenResponseError(\n response: Response,\n): Promise<VoiceInputError> {\n const retryAfterMs = parseRetryAfter(response.headers.get(\"Retry-After\"));\n if (response.status === 401 || response.status === 403) {\n return new VoiceInputError({\n code: \"unauthorized\",\n message: \"The Deepgram token endpoint rejected this request.\",\n provider: \"deepgram\",\n });\n }\n if (response.status === 429) {\n return new VoiceInputError({\n code: \"rate-limited\",\n message: \"The Deepgram token endpoint rate limit was exceeded.\",\n provider: \"deepgram\",\n retryable: true,\n ...(retryAfterMs === undefined ? {} : { retryAfterMs }),\n });\n }\n const safeError = await readSafeTokenError(response);\n if (safeError !== undefined) {\n return new VoiceInputError({ ...safeError, provider: \"deepgram\" });\n }\n return new VoiceInputError({\n code: \"token-error\",\n message: \"The Deepgram token endpoint did not issue a token.\",\n provider: \"deepgram\",\n retryable: response.status >= 500,\n });\n}\n\nasync function readSafeTokenError(response: Response): Promise<\n | {\n code: \"invalid-configuration\" | \"unsupported-feature\";\n message: string;\n }\n | undefined\n> {\n if (\n response.status !== 400 ||\n response.headers.get(\"X-VoiceInput-Error\") !== \"1\" ||\n response.headers.get(\"Content-Type\")?.split(\";\", 1)[0]?.trim() !==\n \"application/json\"\n ) {\n return undefined;\n }\n const text = await readBoundedErrorText(response);\n if (text === undefined) return undefined;\n try {\n const value = JSON.parse(text) as unknown;\n const error = isRecord(value) ? value[\"error\"] : undefined;\n if (\n !isRecord(error) ||\n (error[\"code\"] !== \"invalid-configuration\" &&\n error[\"code\"] !== \"unsupported-feature\") ||\n typeof error[\"message\"] !== \"string\" ||\n error[\"message\"].length === 0 ||\n error[\"message\"].length > 1_000\n ) {\n return undefined;\n }\n return { code: error[\"code\"], message: error[\"message\"] };\n } catch {\n return undefined;\n }\n}\n\nasync function readBoundedErrorText(\n response: Response,\n): Promise<string | undefined> {\n const reader = response.body?.getReader();\n if (reader === undefined) return undefined;\n const decoder = new TextDecoder();\n let bytesRead = 0;\n let text = \"\";\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) return text + decoder.decode();\n bytesRead += value.byteLength;\n if (bytesRead > 4_096) {\n await reader.cancel().catch(() => {});\n return undefined;\n }\n text += decoder.decode(value, { stream: true });\n }\n } catch {\n return undefined;\n }\n}\n\nfunction waitForOpen(\n socket: WebSocket,\n abortSignal: AbortSignal,\n): Promise<void> {\n if (socket.readyState === 1) {\n return Promise.resolve();\n }\n return new Promise((resolve, reject) => {\n const cleanup = (): void => {\n socket.removeEventListener(\"open\", handleOpen);\n socket.removeEventListener(\"error\", handleError);\n abortSignal.removeEventListener(\"abort\", handleAbort);\n };\n const handleOpen = (): void => {\n cleanup();\n resolve();\n };\n const handleError = (event: Event): void => {\n cleanup();\n reject(\n new VoiceInputError({\n code: \"network-error\",\n message: \"Unable to open the Deepgram streaming connection.\",\n provider: \"deepgram\",\n retryable: true,\n cause: event,\n }),\n );\n };\n const handleAbort = (): void => {\n cleanup();\n reject(abortSignal.reason);\n };\n socket.addEventListener(\"open\", handleOpen, { once: true });\n socket.addEventListener(\"error\", handleError, { once: true });\n abortSignal.addEventListener(\"abort\", handleAbort, { once: true });\n });\n}\n\nfunction sendJson(socket: WebSocket, value: Record<string, unknown>): void {\n try {\n socket.send(JSON.stringify(value));\n } catch (cause) {\n throw new VoiceInputError({\n code: \"network-error\",\n message: \"Unable to send data to Deepgram.\",\n provider: \"deepgram\",\n retryable: true,\n cause,\n });\n }\n}\n\nfunction parseRetryAfter(value: string | null): number | undefined {\n if (value === null) {\n return undefined;\n }\n const seconds = Number(value);\n if (Number.isFinite(seconds) && seconds >= 0) {\n return Math.ceil(seconds * 1_000);\n }\n const date = Date.parse(value);\n return Number.isNaN(date) ? undefined : Math.max(0, date - Date.now());\n}\n\nfunction throwIfAborted(signal: AbortSignal): void {\n if (signal.aborted) {\n throw signal.reason;\n }\n}\n\nfunction nonEmpty(value: unknown): value is string {\n return typeof value === \"string\" && value.length > 0;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nexport { DEEPGRAM_DEFAULT_MODEL } from \"./session-config.js\";\n"],"mappings":"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"}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { VoiceInputProviderV1 } from "@voiceinput/provider";
|
|
2
|
+
//#region src/session-config.d.ts
|
|
3
|
+
declare const DEEPGRAM_DEFAULT_MODEL = "nova-3";
|
|
4
|
+
interface DeepgramRealtimeSettings {
|
|
5
|
+
readonly smartFormat?: boolean;
|
|
6
|
+
readonly punctuate?: boolean;
|
|
7
|
+
readonly profanityFilter?: boolean;
|
|
8
|
+
readonly numerals?: boolean;
|
|
9
|
+
}
|
|
10
|
+
//#endregion
|
|
11
|
+
//#region src/index.d.ts
|
|
12
|
+
interface DeepgramVoiceInputProviderOptions extends DeepgramRealtimeSettings {
|
|
13
|
+
readonly tokenEndpoint: string | URL;
|
|
14
|
+
readonly model?: string;
|
|
15
|
+
readonly fetch?: typeof globalThis.fetch;
|
|
16
|
+
readonly webSocket?: typeof globalThis.WebSocket;
|
|
17
|
+
readonly realtimeUrl?: string;
|
|
18
|
+
}
|
|
19
|
+
declare function deepgram(options: DeepgramVoiceInputProviderOptions): VoiceInputProviderV1;
|
|
20
|
+
//#endregion
|
|
21
|
+
export { DEEPGRAM_DEFAULT_MODEL, DeepgramVoiceInputProviderOptions, deepgram };
|
|
22
|
+
//# sourceMappingURL=index.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/session-config.ts","../src/index.ts"],"mappings":";;cAKa;UAYI;WACN;WACA;WACA;WACA;;;;UCAM,0CAA0C;WAChD,wBAAwB;WACxB;WACA,eAAe,WAAW;WAC1B,mBAAmB,WAAW;WAC9B;;iBAGK,SACd,SAAS,oCACR"}
|