@tryhakim/voice 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +188 -0
- package/dist/audio/speech-stream-ws.d.ts +40 -0
- package/dist/audio/speech-stream-ws.d.ts.map +1 -0
- package/dist/audio/speech-stream-ws.js +565 -0
- package/dist/audio/speech-stream-ws.js.map +1 -0
- package/dist/audio/speech.d.ts +46 -0
- package/dist/audio/speech.d.ts.map +1 -0
- package/dist/audio/speech.js +125 -0
- package/dist/audio/speech.js.map +1 -0
- package/dist/audio/stream.d.ts +38 -0
- package/dist/audio/stream.d.ts.map +1 -0
- package/dist/audio/stream.js +452 -0
- package/dist/audio/stream.js.map +1 -0
- package/dist/audio/to-blob.d.ts +10 -0
- package/dist/audio/to-blob.d.ts.map +1 -0
- package/dist/audio/to-blob.js +78 -0
- package/dist/audio/to-blob.js.map +1 -0
- package/dist/audio/transcriptions.d.ts +35 -0
- package/dist/audio/transcriptions.d.ts.map +1 -0
- package/dist/audio/transcriptions.js +105 -0
- package/dist/audio/transcriptions.js.map +1 -0
- package/dist/audio/translate-stream-ws.d.ts +37 -0
- package/dist/audio/translate-stream-ws.d.ts.map +1 -0
- package/dist/audio/translate-stream-ws.js +665 -0
- package/dist/audio/translate-stream-ws.js.map +1 -0
- package/dist/audio/translate.d.ts +36 -0
- package/dist/audio/translate.d.ts.map +1 -0
- package/dist/audio/translate.js +39 -0
- package/dist/audio/translate.js.map +1 -0
- package/dist/audio/voices.d.ts +47 -0
- package/dist/audio/voices.d.ts.map +1 -0
- package/dist/audio/voices.js +91 -0
- package/dist/audio/voices.js.map +1 -0
- package/dist/chat/completions.d.ts +76 -0
- package/dist/chat/completions.d.ts.map +1 -0
- package/dist/chat/completions.js +114 -0
- package/dist/chat/completions.js.map +1 -0
- package/dist/chat/index.d.ts +2 -0
- package/dist/chat/index.d.ts.map +1 -0
- package/dist/chat/index.js +2 -0
- package/dist/chat/index.js.map +1 -0
- package/dist/chat/sse.d.ts +12 -0
- package/dist/chat/sse.d.ts.map +1 -0
- package/dist/chat/sse.js +142 -0
- package/dist/chat/sse.js.map +1 -0
- package/dist/client.d.ts +63 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +80 -0
- package/dist/client.js.map +1 -0
- package/dist/errors.d.ts +99 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +158 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/dist/jobs.d.ts +34 -0
- package/dist/jobs.d.ts.map +1 -0
- package/dist/jobs.js +62 -0
- package/dist/jobs.js.map +1 -0
- package/dist/observability.d.ts +28 -0
- package/dist/observability.d.ts.map +1 -0
- package/dist/observability.js +107 -0
- package/dist/observability.js.map +1 -0
- package/dist/settings.d.ts +49 -0
- package/dist/settings.d.ts.map +1 -0
- package/dist/settings.js +84 -0
- package/dist/settings.js.map +1 -0
- package/dist/transport.d.ts +82 -0
- package/dist/transport.d.ts.map +1 -0
- package/dist/transport.js +289 -0
- package/dist/transport.js.map +1 -0
- package/dist/types.d.ts +969 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +11 -0
- package/dist/types.js.map +1 -0
- package/dist/usage.d.ts +43 -0
- package/dist/usage.d.ts.map +1 -0
- package/dist/usage.js +85 -0
- package/dist/usage.js.map +1 -0
- package/dist/version.d.ts +13 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +13 -0
- package/dist/version.js.map +1 -0
- package/dist/webhooks.d.ts +84 -0
- package/dist/webhooks.d.ts.map +1 -0
- package/dist/webhooks.js +157 -0
- package/dist/webhooks.js.map +1 -0
- package/package.json +57 -0
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,969 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public request/response shapes for the SDK.
|
|
3
|
+
*
|
|
4
|
+
* The types here are hand-kept in lockstep with the Hakim API's
|
|
5
|
+
* request/response contract.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Public TTS model identifiers.
|
|
9
|
+
*
|
|
10
|
+
* The released tier is:
|
|
11
|
+
*
|
|
12
|
+
* - `'hakim-fast-v1'` — sub-120 ms streaming. Recommended for
|
|
13
|
+
* new code that needs the lowest latency.
|
|
14
|
+
*
|
|
15
|
+
* The remaining tiers are kept on this union because the SDK
|
|
16
|
+
* ships one binary for every environment; submitting them to a
|
|
17
|
+
* production API returns `422 model_unavailable` until the org-
|
|
18
|
+
* wide launch flag flips:
|
|
19
|
+
*
|
|
20
|
+
* - `'hakim-v2'` · **`@experimental`** — premium quality with
|
|
21
|
+
* non-verbal tag support. Private preview only today.
|
|
22
|
+
* - `'hakim-v3'` · **`@experimental`** — premium quality plus
|
|
23
|
+
* voice generation via `voice_prompt`. Private preview only
|
|
24
|
+
* today.
|
|
25
|
+
*
|
|
26
|
+
* Plus one legacy alias still accepted by the API:
|
|
27
|
+
*
|
|
28
|
+
* - `'hakim-flash-v1'` — pre-launch codename, normalised to
|
|
29
|
+
* `'hakim-fast-v1'` in metrics, audit logs, and the `model`
|
|
30
|
+
* field of any response surface that echoes it back.
|
|
31
|
+
*
|
|
32
|
+
* SDKs default to {@link DEFAULT_TTS_MODEL} for new requests. See
|
|
33
|
+
* the `audio.ts` + `tts-models.ts` docblocks in `@hakim/schemas`
|
|
34
|
+
* for the tier-ladder rationale.
|
|
35
|
+
*
|
|
36
|
+
* @experimental Members `'hakim-v2'` and `'hakim-v3'` are not
|
|
37
|
+
* generally available — see private-preview note above.
|
|
38
|
+
*/
|
|
39
|
+
export type TTSModel = 'hakim-fast-v1' | 'hakim-v2' | 'hakim-v3' | 'hakim-flash-v1';
|
|
40
|
+
/** Recommended default for new code. */
|
|
41
|
+
export declare const DEFAULT_TTS_MODEL: TTSModel;
|
|
42
|
+
export type ResponseFormat = 'mp3' | 'wav' | 'pcm' | 'opus';
|
|
43
|
+
export type SampleRate = 8000 | 16000 | 22050 | 24000 | 44100 | 48000;
|
|
44
|
+
export interface SpeechRequest {
|
|
45
|
+
model: TTSModel;
|
|
46
|
+
input: string;
|
|
47
|
+
voice: string;
|
|
48
|
+
response_format?: ResponseFormat;
|
|
49
|
+
sample_rate?: SampleRate;
|
|
50
|
+
speed?: number;
|
|
51
|
+
stream?: boolean;
|
|
52
|
+
cfg?: number;
|
|
53
|
+
/**
|
|
54
|
+
* Optional free-form description of a voice. Honoured by
|
|
55
|
+
* tiers that advertise the `voice_prompt` capability (today
|
|
56
|
+
* the `hakim-v3` private preview). On released tiers the
|
|
57
|
+
* field is silently dropped and the response carries a
|
|
58
|
+
* `voice_prompt_dropped_by_model_capability` entry in the
|
|
59
|
+
* `x-hakim-warnings` header.
|
|
60
|
+
*
|
|
61
|
+
* @experimental
|
|
62
|
+
*/
|
|
63
|
+
voice_prompt?: string;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Public STT model identifier.
|
|
67
|
+
*
|
|
68
|
+
* `'hakim-arab-v2'` is the only accepted id — the Arabic-first
|
|
69
|
+
* acoustic profile that backs every transcription path (batch
|
|
70
|
+
* `POST /v1/audio/transcriptions` and realtime
|
|
71
|
+
* `WSS /v1/audio/transcriptions/stream`).
|
|
72
|
+
*
|
|
73
|
+
* SDKs default to {@link DEFAULT_STT_MODEL}.
|
|
74
|
+
*/
|
|
75
|
+
export type STTModel = 'hakim-arab-v2';
|
|
76
|
+
/** The STT model used for every request. */
|
|
77
|
+
export declare const DEFAULT_STT_MODEL: STTModel;
|
|
78
|
+
export type STTResponseFormat = 'json' | 'text' | 'srt' | 'vtt' | 'verbose_json';
|
|
79
|
+
export type STTTimestamps = 'word' | 'segment' | 'none';
|
|
80
|
+
/**
|
|
81
|
+
* Arabic dialect BCP-47 codes the server accepts. Kept in lockstep with
|
|
82
|
+
* `ArabicDialectCode` in `@hakim/schemas/languages.ts` — if you add a
|
|
83
|
+
* dialect there, mirror it here and update the drift test manifest.
|
|
84
|
+
*
|
|
85
|
+
* Phase 4 (voice catalogue v2) widened this list from 7 to 12 codes so
|
|
86
|
+
* cloned voices can pin to a per-country dialect (`ar-EG`, `ar-LB`, …)
|
|
87
|
+
* rather than collapsing everything to MSA.
|
|
88
|
+
*/
|
|
89
|
+
export type ArabicDialectCode = 'ar-SA' | 'ar-AE' | 'ar-EG' | 'ar-SY' | 'ar-LB' | 'ar-JO' | 'ar-PS' | 'ar-MA' | 'ar-DZ' | 'ar-IQ' | 'ar-SD' | 'ar-YE';
|
|
90
|
+
/**
|
|
91
|
+
* ISO 639-1 base language codes the server accepts. `auto` is NOT in
|
|
92
|
+
* this union on purpose — it's an STT-only sentinel, exposed via
|
|
93
|
+
* {@link STTLanguage}. Cloned voices must pin to a real language.
|
|
94
|
+
*/
|
|
95
|
+
export type BaseLanguageCode = 'ar' | 'en' | 'fr' | 'es' | 'de' | 'it' | 'pt' | 'tr' | 'ur' | 'hi' | 'fa' | 'he' | 'nl' | 'ru' | 'pl' | 'uk' | 'ja' | 'ko' | 'zh' | 'th' | 'vi' | 'id' | 'ms' | 'sw' | 'am' | 'bn' | 'ta' | 'el' | 'ps' | 'ku' | 'cs' | 'ro' | 'hu' | 'fi' | 'sv' | 'no' | 'da' | 'my' | 'km' | 'lo' | 'tl';
|
|
96
|
+
/**
|
|
97
|
+
* Language hint for STT: a base ISO code, an Arabic dialect, or `auto`
|
|
98
|
+
* to let the server detect. Matches `STTLanguage` in `@hakim/schemas`.
|
|
99
|
+
*/
|
|
100
|
+
export type STTLanguage = 'auto' | BaseLanguageCode | ArabicDialectCode;
|
|
101
|
+
/**
|
|
102
|
+
* Audio input for STT. Accepts a Node stream, a Buffer, a TypedArray,
|
|
103
|
+
* a File/Blob-like object, or a string (treated as a file path only
|
|
104
|
+
* when `filename` is NOT provided — otherwise the string is the raw
|
|
105
|
+
* body and `filename` is the label we attach to the multipart part).
|
|
106
|
+
*/
|
|
107
|
+
export type AudioInput = Blob | ArrayBuffer | ArrayBufferView | Uint8Array | Buffer | NodeJS.ReadableStream;
|
|
108
|
+
export interface TranscriptionRequestCommon {
|
|
109
|
+
model?: STTModel;
|
|
110
|
+
language?: STTLanguage;
|
|
111
|
+
response_format?: STTResponseFormat;
|
|
112
|
+
timestamps?: STTTimestamps;
|
|
113
|
+
diarize?: boolean;
|
|
114
|
+
/** Explicit filename for the multipart part. If missing, the SDK uses
|
|
115
|
+
* `audio.bin` — the upstream ffprobe step sniffs the real format. */
|
|
116
|
+
filename?: string;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Either upload audio bytes (`file`) or point at a publicly fetchable
|
|
120
|
+
* URL (`url`, e.g. an S3/GCS/Azure presigned link) and let the server
|
|
121
|
+
* fetch it — handy for buckets full of recordings. Exactly one is
|
|
122
|
+
* required; they're mutually exclusive.
|
|
123
|
+
*/
|
|
124
|
+
export type TranscriptionRequest = TranscriptionRequestCommon & ({
|
|
125
|
+
file: AudioInput;
|
|
126
|
+
url?: never;
|
|
127
|
+
} | {
|
|
128
|
+
url: string;
|
|
129
|
+
file?: never;
|
|
130
|
+
});
|
|
131
|
+
/** Parsed JSON response when `response_format: 'json'`. */
|
|
132
|
+
export interface TranscriptionJsonResponse {
|
|
133
|
+
text: string;
|
|
134
|
+
language?: string;
|
|
135
|
+
duration?: number;
|
|
136
|
+
/**
|
|
137
|
+
* Enterprise usage observability · OpenAI-shaped `usage` block
|
|
138
|
+
* mirroring `UsageBlockSchema` in `@hakim/schemas`. Server emits
|
|
139
|
+
* this whenever the call resolved an API-key context (live keys);
|
|
140
|
+
* test keys (`hk_test_…`) keep the legacy shape without `usage`.
|
|
141
|
+
*/
|
|
142
|
+
usage?: UsageBlock;
|
|
143
|
+
}
|
|
144
|
+
/** 202 async acceptance body when the upload exceeds sync limits. */
|
|
145
|
+
export interface TranscriptionAsyncAccepted {
|
|
146
|
+
id: string;
|
|
147
|
+
status: 'queued';
|
|
148
|
+
type: 'stt_batch';
|
|
149
|
+
reason: 'size_gt_25mb' | 'duration_gt_10min';
|
|
150
|
+
limits?: {
|
|
151
|
+
max_sync_size_bytes?: number;
|
|
152
|
+
max_sync_duration_seconds?: number;
|
|
153
|
+
};
|
|
154
|
+
poll_url: string;
|
|
155
|
+
}
|
|
156
|
+
export type TranscriptionResult = {
|
|
157
|
+
kind: 'sync_json';
|
|
158
|
+
data: TranscriptionJsonResponse;
|
|
159
|
+
} | {
|
|
160
|
+
kind: 'sync_text';
|
|
161
|
+
text: string;
|
|
162
|
+
} | {
|
|
163
|
+
kind: 'sync_srt';
|
|
164
|
+
text: string;
|
|
165
|
+
} | {
|
|
166
|
+
kind: 'sync_vtt';
|
|
167
|
+
text: string;
|
|
168
|
+
} | {
|
|
169
|
+
kind: 'async_accepted';
|
|
170
|
+
data: TranscriptionAsyncAccepted;
|
|
171
|
+
};
|
|
172
|
+
export type VoiceKind = 'preset' | 'cloned';
|
|
173
|
+
/**
|
|
174
|
+
* Language a voice is pinned to. Phase 4 (voice catalogue v2) widened
|
|
175
|
+
* this union from `'ar' | 'en' | 'multi'` to the full STT-aligned set —
|
|
176
|
+
* 37 base codes plus 12 Arabic dialects — so cloned voices can surface
|
|
177
|
+
* country-specific Arabic and any language the model supports.
|
|
178
|
+
*
|
|
179
|
+
* `multi` is retained as a deprecated alias for legacy presets and old
|
|
180
|
+
* SDK callers; new voices should pick a concrete base code instead.
|
|
181
|
+
*
|
|
182
|
+
* Kept in lockstep with `VoiceLanguage` in `@hakim/schemas/languages.ts`.
|
|
183
|
+
*/
|
|
184
|
+
export type VoiceLanguage = BaseLanguageCode | ArabicDialectCode | 'multi';
|
|
185
|
+
export type VoiceGender = 'male' | 'female' | 'neutral';
|
|
186
|
+
export type VoiceStatus = 'processing' | 'ready' | 'failed';
|
|
187
|
+
/**
|
|
188
|
+
* Voice use-case / tone. Phase 4 (voice catalogue v2) introduced this
|
|
189
|
+
* column so a single speaker identity can have distinct takes per
|
|
190
|
+
* intent (a warm narrator vs. the same speaker reading the news).
|
|
191
|
+
*
|
|
192
|
+
* Kept in lockstep with `VoiceType` in `@hakim/schemas/languages.ts`.
|
|
193
|
+
*/
|
|
194
|
+
export type VoiceType = 'conversational' | 'narrative' | 'news' | 'social_media' | 'advertising' | 'elearning' | 'character' | 'customer_service';
|
|
195
|
+
export interface Voice {
|
|
196
|
+
id: string;
|
|
197
|
+
slug: string;
|
|
198
|
+
name: string;
|
|
199
|
+
kind: VoiceKind;
|
|
200
|
+
language: VoiceLanguage;
|
|
201
|
+
/** Voice use-case / tone. Defaults server-side to `conversational`
|
|
202
|
+
* for presets and for clones that omit the field. */
|
|
203
|
+
voice_type: VoiceType;
|
|
204
|
+
gender: VoiceGender;
|
|
205
|
+
description: string | null;
|
|
206
|
+
preview_url: string | null;
|
|
207
|
+
status: VoiceStatus;
|
|
208
|
+
created_at?: string;
|
|
209
|
+
}
|
|
210
|
+
export interface VoicesListQuery {
|
|
211
|
+
language?: VoiceLanguage;
|
|
212
|
+
gender?: VoiceGender;
|
|
213
|
+
kind?: VoiceKind;
|
|
214
|
+
/** Filter by voice use-case / tone (Phase 4). */
|
|
215
|
+
voice_type?: VoiceType;
|
|
216
|
+
}
|
|
217
|
+
export interface VoicesListResponse {
|
|
218
|
+
object: 'list';
|
|
219
|
+
data: Voice[];
|
|
220
|
+
}
|
|
221
|
+
export type UsageKind = 'tts' | 'stt_batch' | 'stt_realtime' | 'voice_clone' | 'video_studio' | 'llm_chat';
|
|
222
|
+
/** Public chat model id. v1 ships a single canonical id; the
|
|
223
|
+
* marketing alias `hkm-llm-1` is also accepted at the route. */
|
|
224
|
+
export type ChatModel = 'hakim-chat-v1' | 'hkm-llm-1';
|
|
225
|
+
/** Roles accepted on a message. `tool` is reserved for the future
|
|
226
|
+
* function-calling rollout — v1 rejects tool messages at the
|
|
227
|
+
* route boundary. */
|
|
228
|
+
export type ChatRole = 'system' | 'user' | 'assistant' | 'tool';
|
|
229
|
+
/** Text content part. Mirrors OpenAI's `type: 'text'` part so
|
|
230
|
+
* callers who already serialise structured content keep the same
|
|
231
|
+
* shape when vision lands in P7. */
|
|
232
|
+
export interface ChatTextContentPart {
|
|
233
|
+
type: 'text';
|
|
234
|
+
text: string;
|
|
235
|
+
}
|
|
236
|
+
/** A message's content is either a flat string (OpenAI shorthand)
|
|
237
|
+
* or an array of structured parts. v1 only ships text parts. */
|
|
238
|
+
export type ChatMessageContent = string | ChatTextContentPart[];
|
|
239
|
+
export interface ChatMessage {
|
|
240
|
+
role: ChatRole;
|
|
241
|
+
content: ChatMessageContent;
|
|
242
|
+
/** OpenAI's optional speaker name. Capped server-side at 64 chars. */
|
|
243
|
+
name?: string;
|
|
244
|
+
/** Function-calling attachments — reserved for P7. Schema accepts
|
|
245
|
+
* them so callers hand-rolling tool calls don't 400 today; the
|
|
246
|
+
* route strips them before upstream dispatch. */
|
|
247
|
+
tool_call_id?: string;
|
|
248
|
+
tool_calls?: unknown[];
|
|
249
|
+
/** Chain-of-thought trace from a reasoning-capable model.
|
|
250
|
+
* Surfaced only on assistant turns and only when the caller
|
|
251
|
+
* opted in via `reasoning: { enabled: true }` on the request.
|
|
252
|
+
* Field name matches OpenRouter / OpenAI gpt-oss cookbook
|
|
253
|
+
* conventions so existing SDK readers Just Work. */
|
|
254
|
+
reasoning?: string;
|
|
255
|
+
}
|
|
256
|
+
/** Reasoning / chain-of-thought control. Defaults to OFF on every
|
|
257
|
+
* upstream call · thinking adds 10–50× latency for short prompts.
|
|
258
|
+
* Set `enabled: true` on a non-stream request to opt into
|
|
259
|
+
* receiving `message.reasoning` alongside `message.content`.
|
|
260
|
+
* Streaming requests with `reasoning.enabled = true` are rejected
|
|
261
|
+
* at the route's schema layer with a 400 — real-time agents
|
|
262
|
+
* cannot afford the latency cost. */
|
|
263
|
+
export interface ChatReasoningOption {
|
|
264
|
+
enabled: boolean;
|
|
265
|
+
}
|
|
266
|
+
export interface ChatCompletionRequest {
|
|
267
|
+
model: ChatModel | string;
|
|
268
|
+
messages: ChatMessage[];
|
|
269
|
+
/** Default `false`. `true` switches the response to SSE. */
|
|
270
|
+
stream?: boolean;
|
|
271
|
+
temperature?: number;
|
|
272
|
+
top_p?: number;
|
|
273
|
+
max_tokens?: number;
|
|
274
|
+
/** v1 is locked to `1`. Schema accepts the field; rejects `> 1`. */
|
|
275
|
+
n?: 1;
|
|
276
|
+
stop?: string | string[];
|
|
277
|
+
user?: string;
|
|
278
|
+
presence_penalty?: number;
|
|
279
|
+
frequency_penalty?: number;
|
|
280
|
+
seed?: number;
|
|
281
|
+
/** P7 placeholder. Schema accepts the field; the route strips it
|
|
282
|
+
* before upstream dispatch. */
|
|
283
|
+
tools?: unknown[];
|
|
284
|
+
tool_choice?: unknown;
|
|
285
|
+
/** Reasoning / chain-of-thought control. Stream + `enabled:true`
|
|
286
|
+
* combo is rejected with a 400. */
|
|
287
|
+
reasoning?: ChatReasoningOption;
|
|
288
|
+
}
|
|
289
|
+
/** Finish reasons forwarded verbatim from the upstream. */
|
|
290
|
+
export type ChatFinishReason = 'stop' | 'length' | 'content_filter' | 'tool_calls' | 'function_call';
|
|
291
|
+
export interface ChatCompletionUsage {
|
|
292
|
+
prompt_tokens: number;
|
|
293
|
+
completion_tokens: number;
|
|
294
|
+
total_tokens: number;
|
|
295
|
+
}
|
|
296
|
+
export interface ChatCompletionChoice {
|
|
297
|
+
index: number;
|
|
298
|
+
message: ChatMessage;
|
|
299
|
+
finish_reason: ChatFinishReason | null;
|
|
300
|
+
}
|
|
301
|
+
export interface ChatCompletionResponse {
|
|
302
|
+
/** Public completion id (`chatcmpl-<rand24>`). Hakim-minted; the
|
|
303
|
+
* upstream id is never echoed. */
|
|
304
|
+
id: string;
|
|
305
|
+
object: 'chat.completion';
|
|
306
|
+
created: number;
|
|
307
|
+
model: string;
|
|
308
|
+
choices: ChatCompletionChoice[];
|
|
309
|
+
usage: ChatCompletionUsage;
|
|
310
|
+
/** Hakim-specific per-request usage block. Same data as the
|
|
311
|
+
* `x-hakim-usage-*` headers; embedded in the body so loggers
|
|
312
|
+
* that strip headers don't lose it. */
|
|
313
|
+
hakim_usage?: UsageBlock;
|
|
314
|
+
}
|
|
315
|
+
/** Streaming `delta` — partial assistant message. Each chunk
|
|
316
|
+
* carries the role (first chunk), a content fragment, or — for
|
|
317
|
+
* reasoning-capable models when the caller opted in — a
|
|
318
|
+
* `reasoning` fragment as a sibling. v1's route rejects the
|
|
319
|
+
* stream-with-reasoning combo, so `delta.reasoning` is never
|
|
320
|
+
* populated on the public wire today; the field is kept on the
|
|
321
|
+
* shape for future non-real-time surfaces. */
|
|
322
|
+
export interface ChatCompletionChunkDelta {
|
|
323
|
+
role?: ChatRole;
|
|
324
|
+
content?: string;
|
|
325
|
+
reasoning?: string;
|
|
326
|
+
}
|
|
327
|
+
export interface ChatCompletionChunkChoice {
|
|
328
|
+
index: number;
|
|
329
|
+
delta: ChatCompletionChunkDelta;
|
|
330
|
+
finish_reason: ChatFinishReason | null;
|
|
331
|
+
}
|
|
332
|
+
export interface ChatCompletionChunk {
|
|
333
|
+
id: string;
|
|
334
|
+
object: 'chat.completion.chunk';
|
|
335
|
+
created: number;
|
|
336
|
+
model: string;
|
|
337
|
+
choices: ChatCompletionChunkChoice[];
|
|
338
|
+
/** Only the final chunk carries `usage` — Together emits it
|
|
339
|
+
* once per stream when configured for OpenAI compatibility,
|
|
340
|
+
* and we forward the same shape. */
|
|
341
|
+
usage?: ChatCompletionUsage;
|
|
342
|
+
}
|
|
343
|
+
/** Decimal-string USD amount (2–6 fractional digits). See
|
|
344
|
+
* `UsdAmountSchema` in `@hakim/schemas` for the rationale (financial
|
|
345
|
+
* pipelines treat it as `DECIMAL(10,4)` cleanly). */
|
|
346
|
+
export type UsdAmount = string;
|
|
347
|
+
/** Unit denomination of a single request — what the integer in
|
|
348
|
+
* `UsageBlock.units` measures. `'tokens'` covers chat
|
|
349
|
+
* completions; the input/output split lives in the underlying
|
|
350
|
+
* `UsageEvent.metadata`. */
|
|
351
|
+
export type UsageUnitType = 'characters' | 'seconds' | 'count' | 'credits' | 'tokens';
|
|
352
|
+
/** Overage mode for the org's plan. `topup` is the current default. */
|
|
353
|
+
export type OverageMode = 'topup' | 'postpaid' | 'hard_stop';
|
|
354
|
+
/** OpenAI-shaped per-request usage block. Surfaced on STT JSON bodies,
|
|
355
|
+
* WebSocket frames, and via the `x-hakim-usage-*` response headers. */
|
|
356
|
+
export interface UsageBlock {
|
|
357
|
+
request_id: string;
|
|
358
|
+
kind: 'tts' | 'stt_batch' | 'stt_realtime' | 'voice_clone' | 'video_studio' | 'llm_chat';
|
|
359
|
+
units: number;
|
|
360
|
+
unit_type: UsageUnitType;
|
|
361
|
+
credits: number;
|
|
362
|
+
cost_usd: UsdAmount;
|
|
363
|
+
model: string | null;
|
|
364
|
+
billing_period_start: string;
|
|
365
|
+
billing_period_end: string;
|
|
366
|
+
}
|
|
367
|
+
export interface CreditsSnapshot {
|
|
368
|
+
included: number;
|
|
369
|
+
used: number;
|
|
370
|
+
remaining: number;
|
|
371
|
+
effective_limit: number;
|
|
372
|
+
}
|
|
373
|
+
export interface ConcurrencySnapshot {
|
|
374
|
+
limit: number;
|
|
375
|
+
current: number;
|
|
376
|
+
}
|
|
377
|
+
export interface RateLimitSnapshot {
|
|
378
|
+
limit_per_minute: number;
|
|
379
|
+
remaining: number;
|
|
380
|
+
reset_at: string;
|
|
381
|
+
}
|
|
382
|
+
export interface PlanSnapshot {
|
|
383
|
+
id: string;
|
|
384
|
+
name: string;
|
|
385
|
+
overage_mode: OverageMode;
|
|
386
|
+
}
|
|
387
|
+
export interface PeriodSnapshot {
|
|
388
|
+
start: string;
|
|
389
|
+
end: string;
|
|
390
|
+
}
|
|
391
|
+
/** Full point-in-time limits envelope returned by `GET /v1/limits` and
|
|
392
|
+
* carried inside the realtime `session.created` WS frame. */
|
|
393
|
+
export interface LimitsSnapshot {
|
|
394
|
+
generated_at: string;
|
|
395
|
+
organization_id: string;
|
|
396
|
+
plan: PlanSnapshot;
|
|
397
|
+
period: PeriodSnapshot;
|
|
398
|
+
credits: CreditsSnapshot;
|
|
399
|
+
concurrency: ConcurrencySnapshot;
|
|
400
|
+
rate_limit: RateLimitSnapshot;
|
|
401
|
+
}
|
|
402
|
+
export interface UsageSummary {
|
|
403
|
+
period: {
|
|
404
|
+
start: string;
|
|
405
|
+
end: string;
|
|
406
|
+
};
|
|
407
|
+
tts: {
|
|
408
|
+
characters: number;
|
|
409
|
+
included: number;
|
|
410
|
+
overage_chars: number;
|
|
411
|
+
};
|
|
412
|
+
stt: {
|
|
413
|
+
seconds: number;
|
|
414
|
+
included: number;
|
|
415
|
+
overage_seconds: number;
|
|
416
|
+
};
|
|
417
|
+
estimated_overage_usd: number;
|
|
418
|
+
/** Canonical credits dimension. */
|
|
419
|
+
credits: CreditsSnapshot;
|
|
420
|
+
/** Plan + overage-mode hint so a single call paints a dashboard card. */
|
|
421
|
+
plan: PlanSnapshot;
|
|
422
|
+
/** In-flight request count + plan ceiling (visibility-only in v1). */
|
|
423
|
+
concurrency: ConcurrencySnapshot;
|
|
424
|
+
/** Decimal-string equivalent of `estimated_overage_usd` for finance
|
|
425
|
+
* pipelines that prefer `DECIMAL` typing over float JSON numbers. */
|
|
426
|
+
estimated_overage_cost_usd: UsdAmount;
|
|
427
|
+
}
|
|
428
|
+
export interface UsageEvent {
|
|
429
|
+
id: string;
|
|
430
|
+
kind: UsageKind;
|
|
431
|
+
units: number;
|
|
432
|
+
api_key_id: string | null;
|
|
433
|
+
request_id: string | null;
|
|
434
|
+
status_code: number | null;
|
|
435
|
+
latency_ms: number | null;
|
|
436
|
+
created_at: string;
|
|
437
|
+
/** Credits charged. Non-2xx rows always carry `0`. */
|
|
438
|
+
credits: number;
|
|
439
|
+
/** Marginal cost as a decimal string · `"0.00"` inside the bundle. */
|
|
440
|
+
cost_usd: UsdAmount;
|
|
441
|
+
}
|
|
442
|
+
/** Detail-shape returned by `GET /v1/usage/events/:id`. Adds `model`
|
|
443
|
+
* lifted from the row's metadata so a header-scraped `request_id` can
|
|
444
|
+
* be dereferenced into a row with the public model identifier. */
|
|
445
|
+
export interface UsageEventDetail extends UsageEvent {
|
|
446
|
+
model: string | null;
|
|
447
|
+
}
|
|
448
|
+
export interface UsageEventsList {
|
|
449
|
+
data: UsageEvent[];
|
|
450
|
+
has_more: boolean;
|
|
451
|
+
next_cursor: string | null;
|
|
452
|
+
}
|
|
453
|
+
export interface UsageEventsQuery {
|
|
454
|
+
kind?: UsageKind;
|
|
455
|
+
limit?: number;
|
|
456
|
+
cursor?: string;
|
|
457
|
+
}
|
|
458
|
+
/** Extra metadata the SDK attaches to every response object (not on
|
|
459
|
+
* binary TTS responses — those return a dedicated stream helper). */
|
|
460
|
+
export interface ResponseMeta {
|
|
461
|
+
/** Echoed `X-Request-Id` from the server. */
|
|
462
|
+
requestId: string | undefined;
|
|
463
|
+
/** Raw `status` of the HTTP response. */
|
|
464
|
+
status: number;
|
|
465
|
+
/** Case-insensitive view over response headers. */
|
|
466
|
+
headers: Headers;
|
|
467
|
+
}
|
|
468
|
+
/** TTS response on the non-streaming path. Contains the full audio body
|
|
469
|
+
* plus SDK-surfaced meta. */
|
|
470
|
+
export interface SpeechResponse {
|
|
471
|
+
/** Audio bytes. Use `arrayBuffer()` / `bytes()` to consume. */
|
|
472
|
+
audio: Uint8Array;
|
|
473
|
+
/** e.g. `audio/mpeg`, `audio/wav`, `audio/pcm;rate=24000`, … */
|
|
474
|
+
contentType: string;
|
|
475
|
+
/** Unicode code-point count billed, from `X-Usage-Characters`. */
|
|
476
|
+
usageCharacters: number | undefined;
|
|
477
|
+
/** Audio duration ms, from `X-Duration-Ms`. */
|
|
478
|
+
durationMs: number | undefined;
|
|
479
|
+
/**
|
|
480
|
+
* Enterprise usage observability · per-request usage block parsed
|
|
481
|
+
* from the `x-hakim-usage-*` response headers. `undefined` only on
|
|
482
|
+
* test keys (`hk_test_…`) which deliberately skip the quota
|
|
483
|
+
* pipeline that produces this block.
|
|
484
|
+
*/
|
|
485
|
+
usage: UsageBlock | undefined;
|
|
486
|
+
/**
|
|
487
|
+
* Partial limits snapshot parsed from the period + concurrency
|
|
488
|
+
* response headers. `rate_limit` is omitted because the SDK can
|
|
489
|
+
* read `x-ratelimit-*` directly when needed; call `usage.limits()`
|
|
490
|
+
* for the full snapshot including `rate_limit.reset_at`.
|
|
491
|
+
*/
|
|
492
|
+
limits: SpeechResponseLimits | undefined;
|
|
493
|
+
meta: ResponseMeta;
|
|
494
|
+
}
|
|
495
|
+
/** TTS streaming response. `stream` yields Uint8Array chunks as they
|
|
496
|
+
* arrive from the server. Iterate with `for await` or pipe to stdout. */
|
|
497
|
+
export interface SpeechStreamResponse {
|
|
498
|
+
stream: AsyncIterable<Uint8Array>;
|
|
499
|
+
contentType: string;
|
|
500
|
+
usageCharacters: number | undefined;
|
|
501
|
+
usage: UsageBlock | undefined;
|
|
502
|
+
limits: SpeechResponseLimits | undefined;
|
|
503
|
+
meta: ResponseMeta;
|
|
504
|
+
}
|
|
505
|
+
/** Header-derived limits snapshot · `rate_limit` is intentionally
|
|
506
|
+
* omitted (it lives in `x-ratelimit-*` and reset is delivered as a
|
|
507
|
+
* duration rather than the absolute `reset_at` carried by
|
|
508
|
+
* `LimitsSnapshot`). Call `usage.limits()` for the full envelope. */
|
|
509
|
+
export interface SpeechResponseLimits {
|
|
510
|
+
plan: PlanSnapshot;
|
|
511
|
+
period: PeriodSnapshot;
|
|
512
|
+
credits: CreditsSnapshot;
|
|
513
|
+
concurrency: ConcurrencySnapshot;
|
|
514
|
+
}
|
|
515
|
+
/** Multipart body for `voices.create()`. The server accepts a single
|
|
516
|
+
* audio sample plus metadata; the clone worker picks up from there and
|
|
517
|
+
* flips `status` from `processing` to `ready` (or `failed`). */
|
|
518
|
+
export interface VoiceCreateRequest {
|
|
519
|
+
/** Single audio sample of the target voice. Accepts the same inputs
|
|
520
|
+
* as STT (`Blob`, `Buffer`, `Uint8Array`, Node `ReadableStream`). */
|
|
521
|
+
sample: AudioInput;
|
|
522
|
+
/** Name the caller will see in dashboards and API list responses. */
|
|
523
|
+
name: string;
|
|
524
|
+
/** Optional short description (≤ 500 chars). */
|
|
525
|
+
description?: string;
|
|
526
|
+
/** Language the sample is in. Cloned voices are pinned to a language.
|
|
527
|
+
* Phase 4 widened this union from `'ar' | 'en' | 'multi'` to the
|
|
528
|
+
* full STT-aligned set (37 bases + 12 Arabic dialects). */
|
|
529
|
+
language: VoiceLanguage;
|
|
530
|
+
/** Optional voice use-case / tone. Defaults server-side to
|
|
531
|
+
* `conversational` when omitted (Phase 4). */
|
|
532
|
+
voice_type?: VoiceType;
|
|
533
|
+
/** Must be `true`. The server rejects anything else with
|
|
534
|
+
* `consent_not_confirmed`. Required by the voice-cloning consent
|
|
535
|
+
* workflow — never default this to `true` on behalf of the user. */
|
|
536
|
+
consent_confirmed: true;
|
|
537
|
+
/** Filename to attach on the multipart part. Defaults to
|
|
538
|
+
* `sample.bin`; upstream ffprobe sniffs the real format. */
|
|
539
|
+
filename?: string;
|
|
540
|
+
}
|
|
541
|
+
export type WebhookEventKey = 'job.completed' | 'voice.ready' | 'voice.failed' | 'usage.threshold.reached' | 'invoice.paid' | 'invoice.payment_failed';
|
|
542
|
+
export interface Webhook {
|
|
543
|
+
id: string;
|
|
544
|
+
url: string;
|
|
545
|
+
events: WebhookEventKey[];
|
|
546
|
+
active: boolean;
|
|
547
|
+
created_at: string;
|
|
548
|
+
}
|
|
549
|
+
/** Result of `webhooks.create()`. Includes the raw `secret` exactly
|
|
550
|
+
* once — the same value is never returned by any other endpoint. */
|
|
551
|
+
export interface WebhookCreated extends Webhook {
|
|
552
|
+
secret: string;
|
|
553
|
+
}
|
|
554
|
+
export interface WebhookCreateRequest {
|
|
555
|
+
url: string;
|
|
556
|
+
events: WebhookEventKey[];
|
|
557
|
+
active?: boolean;
|
|
558
|
+
}
|
|
559
|
+
export interface WebhookUpdateRequest {
|
|
560
|
+
url?: string;
|
|
561
|
+
events?: WebhookEventKey[];
|
|
562
|
+
active?: boolean;
|
|
563
|
+
}
|
|
564
|
+
export interface WebhooksListResponse {
|
|
565
|
+
object: 'list';
|
|
566
|
+
data: Webhook[];
|
|
567
|
+
}
|
|
568
|
+
export type WebhookDeliveryStatus = 'pending' | 'succeeded' | 'failed';
|
|
569
|
+
export interface WebhookDelivery {
|
|
570
|
+
id: string;
|
|
571
|
+
webhook_id: string;
|
|
572
|
+
event: WebhookEventKey;
|
|
573
|
+
status: WebhookDeliveryStatus;
|
|
574
|
+
status_code: number | null;
|
|
575
|
+
attempts: number;
|
|
576
|
+
next_retry_at: string | null;
|
|
577
|
+
delivered_at: string | null;
|
|
578
|
+
created_at: string;
|
|
579
|
+
}
|
|
580
|
+
export interface WebhookDeliveriesListQuery {
|
|
581
|
+
webhook_id?: string;
|
|
582
|
+
status?: WebhookDeliveryStatus;
|
|
583
|
+
limit?: number;
|
|
584
|
+
cursor?: string;
|
|
585
|
+
}
|
|
586
|
+
export interface WebhookDeliveriesListResponse {
|
|
587
|
+
object: 'list';
|
|
588
|
+
data: WebhookDelivery[];
|
|
589
|
+
has_more: boolean;
|
|
590
|
+
next_cursor: string | null;
|
|
591
|
+
}
|
|
592
|
+
export type JobType = 'batch_stt' | 'voice_clone' | 'bulk_tts';
|
|
593
|
+
export type JobStatus = 'queued' | 'processing' | 'succeeded' | 'failed' | 'canceled';
|
|
594
|
+
export interface Job {
|
|
595
|
+
id: string;
|
|
596
|
+
type: JobType;
|
|
597
|
+
status: JobStatus;
|
|
598
|
+
progress_pct: number;
|
|
599
|
+
result_url: string | null;
|
|
600
|
+
error_message: string | null;
|
|
601
|
+
error_code?: string | null;
|
|
602
|
+
created_at: string;
|
|
603
|
+
finished_at: string | null;
|
|
604
|
+
}
|
|
605
|
+
export interface JobsListQuery {
|
|
606
|
+
status?: JobStatus;
|
|
607
|
+
type?: JobType;
|
|
608
|
+
limit?: number;
|
|
609
|
+
cursor?: string;
|
|
610
|
+
}
|
|
611
|
+
export interface JobsListResponse {
|
|
612
|
+
object: 'list';
|
|
613
|
+
data: Job[];
|
|
614
|
+
has_more: boolean;
|
|
615
|
+
next_cursor: string | null;
|
|
616
|
+
}
|
|
617
|
+
export type UserLocale = 'ar' | 'en';
|
|
618
|
+
export interface Profile {
|
|
619
|
+
id: string;
|
|
620
|
+
email: string;
|
|
621
|
+
email_verified: boolean;
|
|
622
|
+
name: string | null;
|
|
623
|
+
locale: UserLocale;
|
|
624
|
+
timezone: string;
|
|
625
|
+
avatar_url: string | null;
|
|
626
|
+
marketing_opt_in: boolean;
|
|
627
|
+
}
|
|
628
|
+
export interface ProfileUpdateRequest {
|
|
629
|
+
name?: string | null;
|
|
630
|
+
locale?: UserLocale;
|
|
631
|
+
timezone?: string;
|
|
632
|
+
marketing_opt_in?: boolean;
|
|
633
|
+
}
|
|
634
|
+
export interface OrganizationSettings {
|
|
635
|
+
id: string;
|
|
636
|
+
name: string;
|
|
637
|
+
slug: string;
|
|
638
|
+
billing_email: string | null;
|
|
639
|
+
default_locale: UserLocale;
|
|
640
|
+
logo_url: string | null;
|
|
641
|
+
}
|
|
642
|
+
export interface OrganizationSettingsUpdateRequest {
|
|
643
|
+
name?: string;
|
|
644
|
+
slug?: string;
|
|
645
|
+
billing_email?: string | null;
|
|
646
|
+
default_locale?: UserLocale;
|
|
647
|
+
}
|
|
648
|
+
export interface NotificationPreferences {
|
|
649
|
+
job_completions: boolean;
|
|
650
|
+
voice_ready: boolean;
|
|
651
|
+
billing_alerts: boolean;
|
|
652
|
+
product_updates: boolean;
|
|
653
|
+
}
|
|
654
|
+
export type NotificationPreferencesUpdateRequest = Partial<NotificationPreferences>;
|
|
655
|
+
export interface TranscriptionStreamOptions {
|
|
656
|
+
model?: STTModel;
|
|
657
|
+
language?: STTLanguage;
|
|
658
|
+
/** Sample rate (Hz) of the audio you're about to send. Defaults to
|
|
659
|
+
* 16000 — the server resamples if it has to but the caller wastes
|
|
660
|
+
* bandwidth by sending the wrong rate. */
|
|
661
|
+
sample_rate?: SampleRate;
|
|
662
|
+
/** Format of the audio frames you'll send. Defaults to `pcm16` which
|
|
663
|
+
* maps to little-endian signed 16-bit PCM. */
|
|
664
|
+
audio_format?: 'pcm16';
|
|
665
|
+
/** Abort signal — closing it sends a clean close frame to the server. */
|
|
666
|
+
signal?: AbortSignal;
|
|
667
|
+
}
|
|
668
|
+
/** Partial hypothesis (interim transcript, refines on every emit). */
|
|
669
|
+
export interface TranscriptionPartialEvent {
|
|
670
|
+
type: 'partial';
|
|
671
|
+
text: string;
|
|
672
|
+
/** Ordinal index within the stream, monotonic. */
|
|
673
|
+
seq: number;
|
|
674
|
+
}
|
|
675
|
+
/** Stable transcript segment — once `final`, a segment's text is
|
|
676
|
+
* committed and the server will never emit a `partial` for it again. */
|
|
677
|
+
export interface TranscriptionFinalEvent {
|
|
678
|
+
type: 'final';
|
|
679
|
+
text: string;
|
|
680
|
+
language?: string;
|
|
681
|
+
/** Start / end offsets from stream-open, in seconds. */
|
|
682
|
+
start?: number;
|
|
683
|
+
end?: number;
|
|
684
|
+
seq: number;
|
|
685
|
+
}
|
|
686
|
+
/** Terminal event with the total metered usage. Always emitted
|
|
687
|
+
* exactly once right before the server closes the socket. */
|
|
688
|
+
export interface TranscriptionUsageEvent {
|
|
689
|
+
type: 'usage';
|
|
690
|
+
seconds: number;
|
|
691
|
+
}
|
|
692
|
+
/** Anything the server surfaces mid-stream (invalid payload, quota
|
|
693
|
+
* tripped, etc). The SDK translates the `code` into a `HakimError`
|
|
694
|
+
* subclass and throws; this shape is what callers see via
|
|
695
|
+
* `for await` iteration. */
|
|
696
|
+
export interface TranscriptionErrorEvent {
|
|
697
|
+
type: 'error';
|
|
698
|
+
code: string;
|
|
699
|
+
message: string;
|
|
700
|
+
}
|
|
701
|
+
export type TranscriptionStreamEvent = TranscriptionPartialEvent | TranscriptionFinalEvent | TranscriptionUsageEvent | TranscriptionErrorEvent;
|
|
702
|
+
/** Handle returned by `audio.transcriptions.stream()`. Callers send
|
|
703
|
+
* audio chunks with `sendAudio(bytes)`, iterate `events` to receive
|
|
704
|
+
* partials / finals, and call `close()` when they're done to flush
|
|
705
|
+
* the final usage event. */
|
|
706
|
+
export interface TranscriptionStreamHandle {
|
|
707
|
+
/** Push a PCM chunk to the server. Buffers internally if the socket
|
|
708
|
+
* isn't open yet; throws if the stream is closed. */
|
|
709
|
+
sendAudio(chunk: Uint8Array | ArrayBuffer | ArrayBufferView | Buffer): void;
|
|
710
|
+
/** AsyncIterable of events. Consume with `for await (const e of
|
|
711
|
+
* handle.events) { … }`. Completes once the server closes. */
|
|
712
|
+
readonly events: AsyncIterable<TranscriptionStreamEvent>;
|
|
713
|
+
/** Signal end-of-audio. The server emits a final `usage` event and
|
|
714
|
+
* closes. Resolves once the close handshake completes. */
|
|
715
|
+
close(): Promise<void>;
|
|
716
|
+
/** Resolves once the server has closed the socket. Useful as an
|
|
717
|
+
* alternative to iterating events when you only care about totals. */
|
|
718
|
+
readonly closed: Promise<void>;
|
|
719
|
+
}
|
|
720
|
+
/** Session-wide defaults applied to every `sendSpeech` call unless
|
|
721
|
+
* the call itself overrides the field. Only fields that are
|
|
722
|
+
* routinely pinned for the lifetime of a session live here — text
|
|
723
|
+
* + the optional `voice` override go on `sendSpeech`. */
|
|
724
|
+
export interface SpeechStreamOptions {
|
|
725
|
+
model?: TTSModel;
|
|
726
|
+
/** Default voice applied when a sendSpeech() omits its own voice.
|
|
727
|
+
* Same accepted shape as the HTTP `/v1/audio/speech` route
|
|
728
|
+
* (Voice.id preferred, slug accepted for prototyping). */
|
|
729
|
+
voice?: string;
|
|
730
|
+
/** Classifier-free guidance scale (0–10). Defaults to 2.0. */
|
|
731
|
+
cfg?: number;
|
|
732
|
+
/** Optional free-form voice prompt. Honoured only on tiers that
|
|
733
|
+
* advertise the `voice_prompt` capability (currently `hakim-v3`). */
|
|
734
|
+
voice_prompt?: string;
|
|
735
|
+
/** Abort signal — closing it sends a clean close frame to the
|
|
736
|
+
* server. */
|
|
737
|
+
signal?: AbortSignal;
|
|
738
|
+
}
|
|
739
|
+
/** Per-utterance request shape passed to `handle.sendSpeech()`. */
|
|
740
|
+
export interface SpeechStreamCreateRequest {
|
|
741
|
+
input: string;
|
|
742
|
+
voice?: string;
|
|
743
|
+
model?: TTSModel;
|
|
744
|
+
cfg?: number;
|
|
745
|
+
voice_prompt?: string;
|
|
746
|
+
/** Client-supplied correlation id; echoed back on every event tied
|
|
747
|
+
* to this utterance (speech.started / speech.done / error). When
|
|
748
|
+
* omitted, the server assigns one shaped `wst_<base36>`. */
|
|
749
|
+
request_id?: string;
|
|
750
|
+
}
|
|
751
|
+
/** Emitted once the server has resolved the voice + dispatched the
|
|
752
|
+
* upstream request. Audio chunks (`speech.audio` events) follow
|
|
753
|
+
* until the matching `speech.done`. */
|
|
754
|
+
export interface SpeechStreamStartedEvent {
|
|
755
|
+
type: 'speech.started';
|
|
756
|
+
request_id: string;
|
|
757
|
+
characters: number;
|
|
758
|
+
sample_rate: number;
|
|
759
|
+
encoding: 'pcm_s16le';
|
|
760
|
+
channels: 1;
|
|
761
|
+
model: string;
|
|
762
|
+
voice: string;
|
|
763
|
+
}
|
|
764
|
+
/** Audio chunk delivered between `speech.started` and `speech.done`.
|
|
765
|
+
* `chunk` is raw PCM-S16LE bytes. The SDK groups these as discrete
|
|
766
|
+
* events so consumers can treat the iterable as the single source
|
|
767
|
+
* of truth instead of juggling a separate binary channel. */
|
|
768
|
+
export interface SpeechStreamAudioEvent {
|
|
769
|
+
type: 'speech.audio';
|
|
770
|
+
request_id: string;
|
|
771
|
+
chunk: Uint8Array;
|
|
772
|
+
}
|
|
773
|
+
/** Terminal per-utterance event. `duration_ms` is the synthesised
|
|
774
|
+
* audio duration computed from the streamed byte count. */
|
|
775
|
+
export interface SpeechStreamDoneEvent {
|
|
776
|
+
type: 'speech.done';
|
|
777
|
+
request_id: string;
|
|
778
|
+
duration_ms: number;
|
|
779
|
+
usage: UsageBlock;
|
|
780
|
+
}
|
|
781
|
+
/** Periodic + terminal usage heartbeat · cumulative characters
|
|
782
|
+
* billed for the session so far. */
|
|
783
|
+
export interface SpeechStreamUsageEvent {
|
|
784
|
+
type: 'session.usage';
|
|
785
|
+
session_characters: number;
|
|
786
|
+
usage: UsageBlock;
|
|
787
|
+
}
|
|
788
|
+
/** Server-emitted error. `fatal` distinguishes a per-utterance
|
|
789
|
+
* failure (`fatal: false`, session continues) from a session
|
|
790
|
+
* terminator (`fatal: true`, socket closes after this event). */
|
|
791
|
+
export interface SpeechStreamErrorEvent {
|
|
792
|
+
type: 'error';
|
|
793
|
+
code: string;
|
|
794
|
+
message: string;
|
|
795
|
+
retryable: boolean;
|
|
796
|
+
fatal: boolean;
|
|
797
|
+
request_id?: string;
|
|
798
|
+
}
|
|
799
|
+
export type SpeechStreamEvent = SpeechStreamStartedEvent | SpeechStreamAudioEvent | SpeechStreamDoneEvent | SpeechStreamUsageEvent | SpeechStreamErrorEvent;
|
|
800
|
+
/** Handle returned by `audio.speech.streamWs()`. Callers request
|
|
801
|
+
* utterances with `sendSpeech({ input, voice?, ... })`, iterate
|
|
802
|
+
* `events` to receive audio chunks + lifecycle events, and call
|
|
803
|
+
* `close()` when done to flush usage and tear down the socket. */
|
|
804
|
+
export interface SpeechStreamHandle {
|
|
805
|
+
/** Request a new utterance. Buffers internally if the socket
|
|
806
|
+
* isn't open yet; throws if the stream is closed. Returns the
|
|
807
|
+
* `request_id` (server-assigned when not supplied) so the caller
|
|
808
|
+
* can correlate events for this utterance. */
|
|
809
|
+
sendSpeech(request: SpeechStreamCreateRequest): string;
|
|
810
|
+
/** Update session-wide defaults (model, voice, cfg, voice_prompt)
|
|
811
|
+
* mid-session. Useful for voice-agent flows that switch personas
|
|
812
|
+
* without reconnecting. */
|
|
813
|
+
updateSession(session: Partial<SpeechStreamOptions>): void;
|
|
814
|
+
/** AsyncIterable of events. Consume with `for await (const e of
|
|
815
|
+
* handle.events) { … }`. Completes once the server closes. */
|
|
816
|
+
readonly events: AsyncIterable<SpeechStreamEvent>;
|
|
817
|
+
/** Convenience iterator that yields only the raw PCM chunks for
|
|
818
|
+
* every utterance, in arrival order, until the socket closes.
|
|
819
|
+
* Equivalent to filtering `events` for `speech.audio.chunk`. */
|
|
820
|
+
readonly audio: AsyncIterable<Uint8Array>;
|
|
821
|
+
/** Signal end-of-session. The server flushes one terminal
|
|
822
|
+
* `session.usage` row then closes. Resolves once the close
|
|
823
|
+
* handshake completes. */
|
|
824
|
+
close(): Promise<void>;
|
|
825
|
+
/** Resolves once the server has closed the socket. */
|
|
826
|
+
readonly closed: Promise<void>;
|
|
827
|
+
}
|
|
828
|
+
/** Session config sent on every `session.update`. The minimal session
|
|
829
|
+
* is `{ target_language: 'en' }` — everything else has a server-side
|
|
830
|
+
* default. */
|
|
831
|
+
export interface TranslateStreamOptions {
|
|
832
|
+
/** Target language code. Required for the first `session.update`. */
|
|
833
|
+
target_language?: BaseLanguageCode;
|
|
834
|
+
/** Source language — `'auto'` lets the STT engine detect. Default `auto`. */
|
|
835
|
+
source_language?: 'auto' | BaseLanguageCode | ArabicDialectCode;
|
|
836
|
+
/** Override the auto-resolved voice. When omitted, the server picks
|
|
837
|
+
* the default voice for `(target_language, gender)`. */
|
|
838
|
+
voice?: string;
|
|
839
|
+
/** Default voice gender — used only when `voice` is unset. Default `female`. */
|
|
840
|
+
gender?: VoiceGender;
|
|
841
|
+
/** Override the STT model. Defaults to `hakim-arab-v2`. */
|
|
842
|
+
model_stt?: STTModel;
|
|
843
|
+
/** Override the LLM model. Defaults to the deployment's configured chat model. */
|
|
844
|
+
model_llm?: ChatModel;
|
|
845
|
+
/** Override the TTS model. Defaults to `hakim-fast-v1`. */
|
|
846
|
+
model_tts?: TTSModel;
|
|
847
|
+
/** Classifier-free guidance scale forwarded to TTS. */
|
|
848
|
+
cfg?: number;
|
|
849
|
+
/** Input audio format. Default `pcm16`. */
|
|
850
|
+
input_audio_format?: 'pcm16' | 'opus' | 'mulaw';
|
|
851
|
+
/** Input sample rate (Hz). Default `16000`. */
|
|
852
|
+
input_sample_rate?: 8000 | 16000 | 22050 | 24000 | 44100 | 48000;
|
|
853
|
+
/** Whether STT should emit interim partial-text frames. Default `true`. */
|
|
854
|
+
partials?: boolean;
|
|
855
|
+
/** Optional override for the translator system prompt. */
|
|
856
|
+
system_prompt?: string;
|
|
857
|
+
/** Abort signal — aborting sends a clean `session.close`. */
|
|
858
|
+
signal?: AbortSignal;
|
|
859
|
+
}
|
|
860
|
+
/** Emitted as soon as the server has resolved the voice + dialed all
|
|
861
|
+
* three upstreams. Carries the merged config + chosen voice. */
|
|
862
|
+
export interface TranslateStreamCreatedEvent {
|
|
863
|
+
type: 'session.created';
|
|
864
|
+
session_id: string;
|
|
865
|
+
voice_id: string;
|
|
866
|
+
voice_slug: string;
|
|
867
|
+
model_stt: string;
|
|
868
|
+
model_llm: string;
|
|
869
|
+
model_tts: string;
|
|
870
|
+
}
|
|
871
|
+
export interface TranslateStreamTranscriptionDeltaEvent {
|
|
872
|
+
type: 'transcription.delta';
|
|
873
|
+
utterance_id: string;
|
|
874
|
+
text: string;
|
|
875
|
+
is_final: boolean;
|
|
876
|
+
}
|
|
877
|
+
export interface TranslateStreamTranscriptionDoneEvent {
|
|
878
|
+
type: 'transcription.done';
|
|
879
|
+
utterance_id: string;
|
|
880
|
+
text: string;
|
|
881
|
+
language?: string;
|
|
882
|
+
audio_ms: number;
|
|
883
|
+
usage: UsageBlock;
|
|
884
|
+
}
|
|
885
|
+
export interface TranslateStreamTranslationDeltaEvent {
|
|
886
|
+
type: 'translation.delta';
|
|
887
|
+
utterance_id: string;
|
|
888
|
+
text: string;
|
|
889
|
+
}
|
|
890
|
+
export interface TranslateStreamTranslationDoneEvent {
|
|
891
|
+
type: 'translation.done';
|
|
892
|
+
utterance_id: string;
|
|
893
|
+
text: string;
|
|
894
|
+
usage: UsageBlock;
|
|
895
|
+
}
|
|
896
|
+
export interface TranslateStreamSpeechStartedEvent {
|
|
897
|
+
type: 'speech.started';
|
|
898
|
+
utterance_id: string;
|
|
899
|
+
characters: number;
|
|
900
|
+
sample_rate: number;
|
|
901
|
+
encoding: 'pcm_s16le';
|
|
902
|
+
channels: 1;
|
|
903
|
+
voice_id: string;
|
|
904
|
+
}
|
|
905
|
+
/** PCM-S16LE chunk for the in-flight utterance. The SDK groups
|
|
906
|
+
* binary frames into events so consumers iterate a single stream. */
|
|
907
|
+
export interface TranslateStreamSpeechAudioEvent {
|
|
908
|
+
type: 'speech.audio';
|
|
909
|
+
utterance_id: string;
|
|
910
|
+
chunk: Uint8Array;
|
|
911
|
+
}
|
|
912
|
+
export interface TranslateStreamSpeechDoneEvent {
|
|
913
|
+
type: 'speech.done';
|
|
914
|
+
utterance_id: string;
|
|
915
|
+
duration_ms: number;
|
|
916
|
+
usage: UsageBlock;
|
|
917
|
+
}
|
|
918
|
+
/** Cross-modality usage rollup — emitted every 30 s and once on close. */
|
|
919
|
+
export interface TranslateStreamSessionUsageEvent {
|
|
920
|
+
type: 'session.usage';
|
|
921
|
+
session_id: string;
|
|
922
|
+
totals: {
|
|
923
|
+
stt_audio_ms: number;
|
|
924
|
+
llm_tokens: number;
|
|
925
|
+
tts_characters: number;
|
|
926
|
+
credits: number;
|
|
927
|
+
cost_usd: string;
|
|
928
|
+
};
|
|
929
|
+
}
|
|
930
|
+
export interface TranslateStreamErrorEvent {
|
|
931
|
+
type: 'error';
|
|
932
|
+
code: string;
|
|
933
|
+
message: string;
|
|
934
|
+
retryable: boolean;
|
|
935
|
+
fatal: boolean;
|
|
936
|
+
utterance_id?: string;
|
|
937
|
+
}
|
|
938
|
+
export type TranslateStreamEvent = TranslateStreamCreatedEvent | TranslateStreamTranscriptionDeltaEvent | TranslateStreamTranscriptionDoneEvent | TranslateStreamTranslationDeltaEvent | TranslateStreamTranslationDoneEvent | TranslateStreamSpeechStartedEvent | TranslateStreamSpeechAudioEvent | TranslateStreamSpeechDoneEvent | TranslateStreamSessionUsageEvent | TranslateStreamErrorEvent;
|
|
939
|
+
/** Handle returned by `audio.translate.streamWs()`. Callers stream
|
|
940
|
+
* audio in with `sendAudio()`, iterate `events` for the full
|
|
941
|
+
* STT → LLM → TTS event catalog (or `audio` for the raw PCM chunks
|
|
942
|
+
* of the synthesised target), and `close()` when done to flush
|
|
943
|
+
* usage and tear down the socket. */
|
|
944
|
+
export interface TranslateStreamHandle {
|
|
945
|
+
/** Append a chunk of source audio (PCM at the configured
|
|
946
|
+
* `input_sample_rate`). Buffers internally if the socket isn't
|
|
947
|
+
* open yet; throws if the stream is closed. */
|
|
948
|
+
sendAudio(chunk: Uint8Array | ArrayBuffer | ArrayBufferView | Buffer): void;
|
|
949
|
+
/** Force an immediate STT utterance boundary. Equivalent to the
|
|
950
|
+
* end-of-speech signal the proxy would otherwise synthesise after
|
|
951
|
+
* a quiet window. */
|
|
952
|
+
commitAudio(): void;
|
|
953
|
+
/** Update session-wide defaults mid-session. Merged into the local
|
|
954
|
+
* copy too so a lazy reopen carries the latest values. */
|
|
955
|
+
updateSession(session: Partial<TranslateStreamOptions>): void;
|
|
956
|
+
/** AsyncIterable of every event. Completes once the server closes. */
|
|
957
|
+
readonly events: AsyncIterable<TranslateStreamEvent>;
|
|
958
|
+
/** Convenience iterator that yields only the synthesised audio
|
|
959
|
+
* bytes (raw PCM-S16LE @ 24 kHz mono), in arrival order, until
|
|
960
|
+
* the socket closes. Equivalent to filtering `events` for
|
|
961
|
+
* `speech.audio.chunk`. */
|
|
962
|
+
readonly audio: AsyncIterable<Uint8Array>;
|
|
963
|
+
/** Signal end-of-session. The server emits a terminal
|
|
964
|
+
* `session.usage` rollup then closes. */
|
|
965
|
+
close(): Promise<void>;
|
|
966
|
+
/** Resolves once the server has closed the socket. */
|
|
967
|
+
readonly closed: Promise<void>;
|
|
968
|
+
}
|
|
969
|
+
//# sourceMappingURL=types.d.ts.map
|