@shogo-ai/voice 1.10.0 → 2.4.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.
Files changed (68) hide show
  1. package/README.md +89 -0
  2. package/dist/{chunk-S3S2RNO6.js → chunk-BI6SL35K.js} +1 -184
  3. package/dist/chunk-CLF25CZC.js +987 -0
  4. package/dist/chunk-KMSL5PWK.js +540 -0
  5. package/dist/chunk-ME3SIZZU.js +581 -0
  6. package/dist/chunk-TQOBJMEK.js +17 -0
  7. package/dist/{chunk-T3T4EBWY.js → chunk-UH75UVM2.js} +6 -2
  8. package/dist/chunk-UW7VQ3S6.js +148 -0
  9. package/dist/chunk-XE4LLC7Z.js +1067 -0
  10. package/dist/chunk-ZAW6F3YT.js +172 -0
  11. package/dist/index.cjs +735 -25
  12. package/dist/index.d.cts +373 -3
  13. package/dist/index.d.ts +373 -3
  14. package/dist/index.js +59 -3
  15. package/dist/live/client.cjs +173 -0
  16. package/dist/live/client.d.cts +132 -0
  17. package/dist/live/client.d.ts +132 -0
  18. package/dist/live/client.js +9 -0
  19. package/dist/native/index.d.cts +5 -2
  20. package/dist/native/index.d.ts +5 -2
  21. package/dist/native/index.js +15 -11
  22. package/dist/{organicParticlesShaders-DIva0vBO.d.ts → organicParticlesShaders-seZq7jYX.d.cts} +1 -421
  23. package/dist/{organicParticlesShaders-DIva0vBO.d.cts → organicParticlesShaders-seZq7jYX.d.ts} +1 -421
  24. package/dist/particlesConfig-0YbdPOdY.d.cts +223 -0
  25. package/dist/particlesConfig-0YbdPOdY.d.ts +223 -0
  26. package/dist/react/conversation.cjs +789 -0
  27. package/dist/react/conversation.d.cts +134 -0
  28. package/dist/react/conversation.d.ts +134 -0
  29. package/dist/react/conversation.js +13 -0
  30. package/dist/react/index.cjs +374 -36
  31. package/dist/react/index.d.cts +10 -141
  32. package/dist/react/index.d.ts +10 -141
  33. package/dist/react/index.js +23 -770
  34. package/dist/react/visuals.cjs +1048 -0
  35. package/dist/react/visuals.d.cts +70 -0
  36. package/dist/react/visuals.d.ts +70 -0
  37. package/dist/react/visuals.js +10 -0
  38. package/dist/route/agent.cjs +1038 -85
  39. package/dist/route/agent.js +3 -3
  40. package/dist/route/audio-tags.cjs +1038 -85
  41. package/dist/route/audio-tags.js +3 -3
  42. package/dist/route/index.cjs +1042 -85
  43. package/dist/route/index.d.cts +19 -3
  44. package/dist/route/index.d.ts +19 -3
  45. package/dist/route/index.js +3 -3
  46. package/dist/route/music.cjs +1038 -85
  47. package/dist/route/music.js +3 -3
  48. package/dist/route/op.cjs +2118 -0
  49. package/dist/route/op.d.cts +43 -0
  50. package/dist/route/op.d.ts +43 -0
  51. package/dist/route/op.js +27 -0
  52. package/dist/route/signed-url.cjs +1038 -85
  53. package/dist/route/signed-url.js +3 -3
  54. package/dist/route/tts-preview.cjs +1038 -85
  55. package/dist/route/tts-preview.d.cts +6 -4
  56. package/dist/route/tts-preview.d.ts +6 -4
  57. package/dist/route/tts-preview.js +3 -3
  58. package/dist/server.cjs +1038 -85
  59. package/dist/server.d.cts +40 -8
  60. package/dist/server.d.ts +40 -8
  61. package/dist/server.js +2 -2
  62. package/dist/types-Bfhu-aQH.d.cts +199 -0
  63. package/dist/types-Bfhu-aQH.d.ts +199 -0
  64. package/dist/{types-W9y6eMj3.d.ts → types-CadjTXNH.d.cts} +193 -12
  65. package/dist/{types-W9y6eMj3.d.cts → types-CadjTXNH.d.ts} +193 -12
  66. package/package.json +21 -1
  67. package/dist/chunk-B4JC3DK2.js +0 -529
  68. package/dist/chunk-O362EJQR.js +0 -524
package/dist/index.d.cts CHANGED
@@ -1,5 +1,6 @@
1
- import { E as Expressivity } from './types-W9y6eMj3.cjs';
2
- export { A as AUDIO_TAGS, a as AUDIO_TAG_GROUPS, b as AudioTag, c as AudioTagGroup, C as CONVAI_SUPPORTED_TTS_MODELS, d as CONVAI_TTS_MODEL_FALLBACK, e as Companion, f as CompanionStore, g as ComposeMusicParams, h as ConvaiClientTool, i as CreateAgentParams, j as CreateCompanionBody, D as DEFAULT_ALLOWED_TAGS, k as DEFAULT_ELEVENLABS_BASE_URL, l as DEFAULT_MUSIC_MODEL, m as DEFAULT_VOICE_SETTINGS, n as EXPRESSIVITY_BLOCK_CLOSE, o as EXPRESSIVITY_BLOCK_OPEN, p as EXPRESSIVITY_OPTIONS, q as ElevenLabsApiError, r as ElevenLabsClient, s as ElevenLabsClientConfig, t as ElevenLabsRequestOptions, u as ElevenLabsResponse, M as MEMORY_CLIENT_TOOLS, P as PatchAgentParams, v as PatchCompanionBody, T as TextToSpeechParams, w as TtsPreviewBody, V as VoiceMemoryStore, x as VoiceSettings, y as VoiceUser, z as buildPreviewLine, B as composeExpressivityBlock, F as normalizeAudioTags, G as normalizeExpressivity, H as normalizeVoiceSettings, I as readAudioTags, J as readExpressivity, K as readVoiceSettings, L as resolveConvaiTtsModel, N as stripAudioTags, O as stripExpressivityBlock } from './types-W9y6eMj3.cjs';
1
+ import { b as Expressivity } from './types-CadjTXNH.cjs';
2
+ export { A as AUDIO_TAGS, c as AUDIO_TAG_GROUPS, d as AudioTag, e as AudioTagGroup, f as CONVAI_SUPPORTED_TTS_MODELS, g as CONVAI_TTS_MODEL_FALLBACK, h as Companion, C as CompanionStore, i as ComposeMusicParams, j as ConvaiClientTool, k as ConvaiTtsModelResolution, l as CreateAgentParams, m as CreateCompanionBody, D as DEFAULT_ALLOWED_TAGS, n as DEFAULT_ELEVENLABS_BASE_URL, o as DEFAULT_MUSIC_MODEL, p as DEFAULT_SOUND_GENERATION_MODEL, q as DEFAULT_SPEECH_TO_TEXT_MODEL, r as DEFAULT_STS_MODEL, s as DEFAULT_TTS_MODEL, t as DEFAULT_VOICE_SETTINGS, u as EXPRESSIVITY_BLOCK_CLOSE, v as EXPRESSIVITY_BLOCK_OPEN, w as EXPRESSIVITY_OPTIONS, x as ElevenLabsApiError, E as ElevenLabsClient, y as ElevenLabsClientConfig, z as ElevenLabsRequestOptions, B as ElevenLabsResponse, M as MEMORY_CLIENT_TOOLS, P as PatchAgentParams, F as PatchCompanionBody, S as SoundEffectsParams, G as SpeechToSpeechParams, T as TTS_FALLBACK_MODEL, H as TextToSpeechParams, I as TextToSpeechResult, J as TranscribeParams, K as TranscriptionResult, L as TtsPreviewBody, N as VOICE_SOUND_GENERATION_MODEL_IDS, O as VOICE_SPEECH_TO_TEXT_MODEL_IDS, Q as VOICE_STS_MODEL_IDS, R as VOICE_TTS_MODELS, U as VOICE_TTS_MODEL_IDS, a as VoiceMemoryStore, W as VoiceSettings, X as VoiceTtsModel, V as VoiceUser, Y as buildPreviewLine, Z as composeExpressivityBlock, _ as getVoiceTtsModel, $ as isModelRelatedTtsFailure, a0 as normalizeAudioTags, a1 as normalizeExpressivity, a2 as normalizeVoiceSettings, a3 as readAudioTags, a4 as readExpressivity, a5 as readVoiceSettings, a6 as resolveConvaiTtsModel, a7 as resolveConvaiTtsModelDetailed, a8 as stripAudioTags, a9 as stripExpressivityBlock } from './types-CadjTXNH.cjs';
3
+ export { LiveAudioConfig, LiveErrorEvent, LiveResponsesDelegation, LiveSession, LiveSessionClosedEvent, LiveSessionConfig, LiveSessionEvent, LiveSessionHandlers, LiveSessionStartedEvent, LiveSessionUsageUpdatedEvent, LiveWebRtcSession, ShogoLiveClient, ShogoLiveClientOptions } from './live/client.cjs';
3
4
 
4
5
  /**
5
6
  * System-prompt composer for the voice agent.
@@ -44,6 +45,375 @@ declare function extractBasePrompt(prompt: string): string;
44
45
  */
45
46
  declare function composeAgentPrompt(basePrompt: string, options?: ComposeAgentPromptOptions): string;
46
47
 
48
+ /**
49
+ * The voice op registry.
50
+ *
51
+ * Every ElevenLabs media endpoint we expose is one row here: its upstream
52
+ * path, its transport, who may call it, how big a body it may take, and what
53
+ * it costs. Route handlers, proxy handlers and the SDK all read this table
54
+ * instead of being hand-written per endpoint — adding an op is a row and a
55
+ * test, never a new route file.
56
+ *
57
+ * Three consumers:
58
+ * - `@shogo-ai/sdk/voice/server` (`handlers.op`) — BYO mode + proxy mode
59
+ * - `@shogo-ai/sdk/voice/route/op` — the drop-in route modules
60
+ * - `apps/api/src/routes/voice-media.ts` — the hosted `/api/voice/op/:opId`
61
+ *
62
+ * Deliberately free of Node and DOM-only APIs: this module is imported by
63
+ * the browser-safe entry point.
64
+ */
65
+ /**
66
+ * How a request body travels in and a response body travels out:
67
+ * - `json-binary` JSON in, audio bytes out (TTS, music, sound effects)
68
+ * - `json-json` JSON in, JSON out (TTS with timestamps, listings)
69
+ * - `multipart-binary` multipart in, audio bytes out (speech-to-speech)
70
+ * - `multipart-json` multipart in, JSON out (speech-to-text)
71
+ *
72
+ * The adapters live next to the executor; a row only names its transport.
73
+ */
74
+ type VoiceOpTransport = 'json-binary' | 'json-json' | 'multipart-binary' | 'multipart-json';
75
+ /**
76
+ * Project permission the caller needs. Kept as a literal union rather than an
77
+ * import from `@shogo/authz` so this package stays free of server deps; the
78
+ * hosted route widens it to `Permission` where it authorizes.
79
+ */
80
+ type VoiceOpPermission = 'project:read' | 'project:update';
81
+ /** What one unit of an op's cost is measured in. */
82
+ type VoiceOpCostUnit = 'character' | 'second' | 'request';
83
+ interface VoiceOpCost {
84
+ /** Metering unit. */
85
+ unit: VoiceOpCostUnit;
86
+ /** How many units one `character` / `second` / `request` is worth. */
87
+ per: number;
88
+ }
89
+ interface VoiceOp {
90
+ id: string;
91
+ method: 'GET' | 'POST';
92
+ /** Canonical hosted path: `/voice/op/<id>`. */
93
+ hostedPath: `/voice/${string}`;
94
+ /**
95
+ * A path a shipped client already calls. Proxy mode forwards here instead
96
+ * of {@link hostedPath} so an SDK upgrade never breaks a running pod.
97
+ */
98
+ legacyHostedPath?: `/voice/${string}`;
99
+ /** Upstream ElevenLabs path, `{name}` filled from {@link pathParams}. */
100
+ upstreamPath: string;
101
+ /** Path params the caller supplies (body field or query param). */
102
+ pathParams?: readonly string[];
103
+ transport: VoiceOpTransport;
104
+ permission: VoiceOpPermission;
105
+ /** Plan gate name, when the op is not on every plan. */
106
+ planGate?: string;
107
+ /** Request body cap; larger → 413. */
108
+ maxBodyBytes: number;
109
+ /**
110
+ * Metering unit. A row without `cost` must be `byoOnly` — you cannot add an
111
+ * op without deciding who pays for it.
112
+ */
113
+ cost?: VoiceOpCost;
114
+ /**
115
+ * Never runs on Shogo's pooled key (cloning, dubbing — they write state onto
116
+ * the account and need a per-project voice registry).
117
+ */
118
+ byoOnly?: boolean;
119
+ /**
120
+ * Use a typed {@link ElevenLabsClient} method instead of the generic
121
+ * `request()` passthrough. Only the ops that need model fallback (TTS) or
122
+ * body composition (music) set this.
123
+ */
124
+ call?: 'textToSpeech' | 'composeMusic';
125
+ /** Accepted model ids; an unknown one is a 400, never a silent clamp. */
126
+ models?: readonly string[];
127
+ /** Model used for the upstream call when the caller sends none. */
128
+ defaultModel?: string;
129
+ /** Fall back to the project's default agent voice when none is given. */
130
+ defaultVoiceId?: boolean;
131
+ /** Caller field → upstream field. Anything absent here is not forwarded. */
132
+ forward?: Readonly<Record<string, string>>;
133
+ /** Caller fields that must be present (before mapping). */
134
+ required?: readonly string[];
135
+ /** Query params forwarded upstream. */
136
+ queryForward?: readonly string[];
137
+ /** Upstream response headers worth passing through. */
138
+ responseHeaders?: readonly string[];
139
+ /** `Accept` sent upstream (and used when ElevenLabs sends no content-type). */
140
+ accept?: string;
141
+ /** Error label for an upstream failure; defaults to `${id} failed`. */
142
+ errorLabel?: string;
143
+ /**
144
+ * Extra body check the declarative fields cannot express (e.g. music's
145
+ * prompt XOR compositionPlan). Returns an error message or `null`.
146
+ */
147
+ validate?: (fields: Record<string, unknown>) => string | null;
148
+ }
149
+ /**
150
+ * The registry. Order is the order unknown-op errors list ids in.
151
+ *
152
+ * `as const satisfies` is what makes an op cost exactly one row: the ids are
153
+ * derived from the table ({@link VoiceOpId}, {@link VOICE_OP_IDS}) instead of
154
+ * being listed a second time, while `satisfies` still type-checks every field.
155
+ */
156
+ declare const VOICE_OPS: readonly [{
157
+ readonly id: "text-to-speech";
158
+ readonly method: "POST";
159
+ readonly hostedPath: "/voice/op/text-to-speech";
160
+ readonly legacyHostedPath: "/voice/tts";
161
+ readonly upstreamPath: "/v1/text-to-speech/{voiceId}";
162
+ readonly pathParams: readonly ["voiceId"];
163
+ readonly transport: "json-binary";
164
+ readonly call: "textToSpeech";
165
+ readonly permission: "project:read";
166
+ readonly maxBodyBytes: number;
167
+ readonly cost: {
168
+ readonly unit: "character";
169
+ readonly per: 1;
170
+ };
171
+ readonly models: readonly string[];
172
+ readonly defaultModel: "eleven_v4_turbo";
173
+ readonly defaultVoiceId: true;
174
+ readonly forward: {
175
+ readonly text: "text";
176
+ readonly voiceId: "voice_id";
177
+ readonly modelId: "model_id";
178
+ readonly voiceSettings: "voice_settings";
179
+ };
180
+ readonly required: readonly ["text"];
181
+ readonly responseHeaders: readonly ["x-tts-model-used", "x-tts-model-requested", "warning"];
182
+ readonly accept: "audio/mpeg";
183
+ readonly errorLabel: "TTS failed";
184
+ }, {
185
+ readonly id: "text-to-speech-with-timestamps";
186
+ readonly method: "POST";
187
+ readonly hostedPath: "/voice/op/text-to-speech-with-timestamps";
188
+ readonly upstreamPath: "/v1/text-to-speech/{voiceId}/with-timestamps";
189
+ readonly pathParams: readonly ["voiceId"];
190
+ readonly transport: "json-json";
191
+ readonly permission: "project:read";
192
+ readonly maxBodyBytes: number;
193
+ readonly cost: {
194
+ readonly unit: "character";
195
+ readonly per: 1;
196
+ };
197
+ readonly models: readonly string[];
198
+ readonly defaultModel: "eleven_v4_turbo";
199
+ readonly defaultVoiceId: true;
200
+ readonly forward: {
201
+ readonly text: "text";
202
+ readonly voiceId: "voice_id";
203
+ readonly modelId: "model_id";
204
+ readonly voiceSettings: "voice_settings";
205
+ readonly outputFormat: "output_format";
206
+ };
207
+ readonly required: readonly ["text"];
208
+ readonly accept: "application/json";
209
+ }, {
210
+ readonly id: "speech-to-speech";
211
+ readonly method: "POST";
212
+ readonly hostedPath: "/voice/op/speech-to-speech";
213
+ readonly upstreamPath: "/v1/speech-to-speech/{voiceId}";
214
+ readonly pathParams: readonly ["voiceId"];
215
+ readonly transport: "multipart-binary";
216
+ readonly permission: "project:read";
217
+ readonly maxBodyBytes: number;
218
+ readonly cost: {
219
+ readonly unit: "second";
220
+ readonly per: 1;
221
+ };
222
+ readonly models: readonly string[];
223
+ readonly defaultModel: "eleven_multilingual_sts_v2";
224
+ readonly defaultVoiceId: true;
225
+ readonly forward: {
226
+ readonly audio: "audio";
227
+ readonly voiceId: "voice_id";
228
+ readonly modelId: "model_id";
229
+ readonly voiceSettings: "voice_settings";
230
+ readonly outputFormat: "output_format";
231
+ readonly fileFormat: "file_format";
232
+ readonly seed: "seed";
233
+ readonly removeBackgroundNoise: "remove_background_noise";
234
+ };
235
+ readonly required: readonly ["audio"];
236
+ readonly accept: "audio/mpeg";
237
+ }, {
238
+ readonly id: "speech-to-text";
239
+ readonly method: "POST";
240
+ readonly hostedPath: "/voice/op/speech-to-text";
241
+ readonly upstreamPath: "/v1/speech-to-text";
242
+ readonly transport: "multipart-json";
243
+ readonly permission: "project:read";
244
+ readonly maxBodyBytes: number;
245
+ readonly cost: {
246
+ readonly unit: "second";
247
+ readonly per: 1;
248
+ };
249
+ readonly models: readonly string[];
250
+ readonly defaultModel: "scribe_v1";
251
+ readonly forward: {
252
+ readonly file: "file";
253
+ readonly modelId: "model_id";
254
+ readonly languageCode: "language_code";
255
+ readonly diarize: "diarize";
256
+ readonly tagAudioEvents: "tag_audio_events";
257
+ readonly numSpeakers: "num_speakers";
258
+ };
259
+ readonly required: readonly ["file"];
260
+ readonly accept: "application/json";
261
+ }, {
262
+ readonly id: "sound-generation";
263
+ readonly method: "POST";
264
+ readonly hostedPath: "/voice/op/sound-generation";
265
+ readonly upstreamPath: "/v1/sound-generation";
266
+ readonly transport: "json-binary";
267
+ readonly permission: "project:read";
268
+ readonly maxBodyBytes: number;
269
+ readonly cost: {
270
+ readonly unit: "second";
271
+ readonly per: 1;
272
+ };
273
+ readonly models: readonly string[];
274
+ readonly defaultModel: "eleven_text_to_sound_v2";
275
+ readonly forward: {
276
+ readonly text: "text";
277
+ readonly durationSeconds: "duration_seconds";
278
+ readonly promptInfluence: "prompt_influence";
279
+ readonly loop: "loop";
280
+ readonly modelId: "model_id";
281
+ };
282
+ readonly queryForward: readonly ["output_format"];
283
+ readonly required: readonly ["text"];
284
+ readonly accept: "audio/mpeg";
285
+ }, {
286
+ readonly id: "music";
287
+ readonly method: "POST";
288
+ readonly hostedPath: "/voice/op/music";
289
+ readonly legacyHostedPath: "/voice/music";
290
+ readonly upstreamPath: "/v1/music";
291
+ readonly transport: "json-binary";
292
+ readonly call: "composeMusic";
293
+ readonly permission: "project:read";
294
+ readonly maxBodyBytes: number;
295
+ readonly cost: {
296
+ readonly unit: "second";
297
+ readonly per: 1;
298
+ };
299
+ readonly models: readonly ["music_v1"];
300
+ readonly defaultModel: "music_v1";
301
+ readonly forward: {
302
+ readonly prompt: "prompt";
303
+ readonly compositionPlan: "composition_plan";
304
+ readonly musicLengthMs: "music_length_ms";
305
+ readonly modelId: "model_id";
306
+ readonly forceInstrumental: "force_instrumental";
307
+ readonly outputFormat: "output_format";
308
+ };
309
+ readonly accept: "audio/mpeg";
310
+ readonly errorLabel: "Music generation failed";
311
+ readonly validate: (fields: Record<string, unknown>) => "Provide exactly one of `prompt` or `compositionPlan`" | null;
312
+ }, {
313
+ readonly id: "voices";
314
+ readonly method: "GET";
315
+ readonly hostedPath: "/voice/op/voices";
316
+ readonly upstreamPath: "/v1/voices";
317
+ readonly transport: "json-json";
318
+ readonly permission: "project:read";
319
+ readonly maxBodyBytes: 0;
320
+ readonly cost: {
321
+ readonly unit: "request";
322
+ readonly per: 1;
323
+ };
324
+ readonly queryForward: readonly ["page_size", "search", "voice_type", "category", "next_page_token"];
325
+ readonly accept: "application/json";
326
+ }, {
327
+ readonly id: "models";
328
+ readonly method: "GET";
329
+ readonly hostedPath: "/voice/op/models";
330
+ readonly upstreamPath: "/v1/models";
331
+ readonly transport: "json-json";
332
+ readonly permission: "project:read";
333
+ readonly maxBodyBytes: 0;
334
+ readonly cost: {
335
+ readonly unit: "request";
336
+ readonly per: 1;
337
+ };
338
+ readonly accept: "application/json";
339
+ }];
340
+ /** Every op id, in registry order. */
341
+ declare const VOICE_OP_IDS: readonly string[];
342
+ /** The literal union of registry ids. */
343
+ type VoiceOpId = (typeof VOICE_OPS)[number]['id'];
344
+ /** Look up a row by id. */
345
+ declare function getVoiceOp(id: string | null | undefined): VoiceOp | undefined;
346
+ /**
347
+ * The hosted path a client should call for this op. Proxy mode uses
348
+ * {@link VoiceOp.legacyHostedPath} when a client may already be pinned to it.
349
+ */
350
+ declare function voiceOpForwardPath(op: VoiceOp): string;
351
+ /** Which body adapter a row uses. */
352
+ declare function voiceOpIsMultipart(op: VoiceOp): boolean;
353
+ /** Whether the op's response is audio bytes. */
354
+ declare function voiceOpReturnsAudio(op: VoiceOp): boolean;
355
+ /** Fill `{param}` placeholders in {@link VoiceOp.upstreamPath}. */
356
+ declare function voiceOpUpstreamPath(op: VoiceOp, params: Readonly<Record<string, string>>): string | {
357
+ error: string;
358
+ };
359
+ /**
360
+ * Reject a caller who has no key for this op. A `byoOnly` row never runs on
361
+ * the pooled key; `credential` says which key the request would have used.
362
+ */
363
+ declare function voiceOpCredentialError(op: VoiceOp, credential: 'pooled' | 'byo'): {
364
+ status: number;
365
+ error: string;
366
+ detail: string;
367
+ } | null;
368
+ /**
369
+ * Validate + normalize a JSON body against a row: whitelist `forward`, check
370
+ * `required`, resolve the model, run the row's own `validate`.
371
+ *
372
+ * Returns the **caller-shaped** fields (camelCase), not the upstream body —
373
+ * mapping happens in {@link voiceOpUpstreamBody}.
374
+ */
375
+ declare function parseVoiceOpJsonBody(op: VoiceOp, raw: unknown): {
376
+ ok: true;
377
+ fields: Record<string, unknown>;
378
+ } | {
379
+ ok: false;
380
+ status: number;
381
+ error: string;
382
+ detail?: string;
383
+ allowed?: readonly string[];
384
+ };
385
+ /**
386
+ * Validate + normalize a multipart body: the same whitelist/required rules,
387
+ * plus a `File` check on every required part (an `audio` part that is really
388
+ * a text field is the caller's bug, not ElevenLabs').
389
+ *
390
+ * `fields` carries the caller-shaped values the parser read — the path params
391
+ * among them. They are dropped from the rebuilt form (repeating them makes
392
+ * ElevenLabs reject the upload), so this is the only way a `voiceId` form part
393
+ * reaches {@link voiceOpPathParams}; ignoring it would send the request to
394
+ * the project default voice and come back 200 with the wrong voice.
395
+ */
396
+ declare function parseVoiceOpForm(op: VoiceOp, form: FormData): {
397
+ ok: true;
398
+ form: FormData;
399
+ fields: Record<string, unknown>;
400
+ } | {
401
+ ok: false;
402
+ status: number;
403
+ error: string;
404
+ detail?: string;
405
+ allowed?: readonly string[];
406
+ };
407
+ /**
408
+ * Map caller fields onto the upstream JSON body (camelCase → snake_case) and
409
+ * drop the path params, which travel in the URL.
410
+ */
411
+ declare function voiceOpUpstreamBody(op: VoiceOp, fields: Readonly<Record<string, unknown>>): Record<string, unknown>;
412
+ /** Path params for a row, taken from the body first and the query second. */
413
+ declare function voiceOpPathParams(op: VoiceOp, fields: Readonly<Record<string, unknown>>, query: {
414
+ get(name: string): string | null;
415
+ }): Record<string, string>;
416
+
47
417
  /**
48
418
  * Thin `fetch`-based Twilio REST client used by Mode A of the SDK's
49
419
  * `TelephonyClient` (self-hosted / BYO keys). Intentionally duplicates
@@ -429,4 +799,4 @@ declare class MockTelephonyClient implements TelephonyClient {
429
799
  */
430
800
  declare function isVoiceMockEnv(): boolean;
431
801
 
432
- export { type AvailableNumber, type ComposeAgentPromptOptions, type CreateTelephonyOptions, DEFAULT_MEMORY_BLOCK, DEFAULT_TWILIO_BASE_URL, DirectTelephonyClient, type DirectTelephonyOptions, Expressivity, HostedRuntimeTokenClient, type HostedRuntimeTokenOptions, HostedTelephonyClient, type HostedTelephonyOptions, type IncomingNumber, MockTelephonyClient, type OutboundCallOptions, type OutboundCallResult, type ProvisionNumberOptions, type ProvisionNumberResult, type ReleaseNumberResult, TelephonyApiError, type TelephonyClient, TelephonyConfigError, TwilioApiError, TwilioClient, type TwilioClientConfig, type VoiceUsageRange, type VoiceUsageSummary, composeAgentPrompt, createTelephonyClient, extractBasePrompt, isVoiceMockEnv, stripMemoryBlock };
802
+ export { type AvailableNumber, type ComposeAgentPromptOptions, type CreateTelephonyOptions, DEFAULT_MEMORY_BLOCK, DEFAULT_TWILIO_BASE_URL, DirectTelephonyClient, type DirectTelephonyOptions, Expressivity, HostedRuntimeTokenClient, type HostedRuntimeTokenOptions, HostedTelephonyClient, type HostedTelephonyOptions, type IncomingNumber, MockTelephonyClient, type OutboundCallOptions, type OutboundCallResult, type ProvisionNumberOptions, type ProvisionNumberResult, type ReleaseNumberResult, TelephonyApiError, type TelephonyClient, TelephonyConfigError, TwilioApiError, TwilioClient, type TwilioClientConfig, VOICE_OPS, VOICE_OP_IDS, type VoiceOp, type VoiceOpCost, type VoiceOpCostUnit, type VoiceOpId, type VoiceOpPermission, type VoiceOpTransport, type VoiceUsageRange, type VoiceUsageSummary, composeAgentPrompt, createTelephonyClient, extractBasePrompt, getVoiceOp, isVoiceMockEnv, parseVoiceOpForm, parseVoiceOpJsonBody, stripMemoryBlock, voiceOpCredentialError, voiceOpForwardPath, voiceOpIsMultipart, voiceOpPathParams, voiceOpReturnsAudio, voiceOpUpstreamBody, voiceOpUpstreamPath };