@shogo-ai/voice 1.9.13 → 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.ts CHANGED
@@ -1,5 +1,6 @@
1
- import { E as Expressivity } from './types-W9y6eMj3.js';
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.js';
1
+ import { b as Expressivity } from './types-CadjTXNH.js';
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.js';
3
+ export { LiveAudioConfig, LiveErrorEvent, LiveResponsesDelegation, LiveSession, LiveSessionClosedEvent, LiveSessionConfig, LiveSessionEvent, LiveSessionHandlers, LiveSessionStartedEvent, LiveSessionUsageUpdatedEvent, LiveWebRtcSession, ShogoLiveClient, ShogoLiveClientOptions } from './live/client.js';
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 };
package/dist/index.js CHANGED
@@ -1,17 +1,46 @@
1
+ import {
2
+ LiveSession,
3
+ ShogoLiveClient
4
+ } from "./chunk-UW7VQ3S6.js";
1
5
  import {
2
6
  CONVAI_SUPPORTED_TTS_MODELS,
3
7
  CONVAI_TTS_MODEL_FALLBACK,
4
8
  DEFAULT_ELEVENLABS_BASE_URL,
5
9
  DEFAULT_MEMORY_BLOCK,
6
10
  DEFAULT_MUSIC_MODEL,
11
+ DEFAULT_SOUND_GENERATION_MODEL,
12
+ DEFAULT_SPEECH_TO_TEXT_MODEL,
13
+ DEFAULT_STS_MODEL,
14
+ DEFAULT_TTS_MODEL,
7
15
  ElevenLabsApiError,
8
16
  ElevenLabsClient,
9
17
  MEMORY_CLIENT_TOOLS,
18
+ TTS_FALLBACK_MODEL,
19
+ VOICE_OPS,
20
+ VOICE_OP_IDS,
21
+ VOICE_SOUND_GENERATION_MODEL_IDS,
22
+ VOICE_SPEECH_TO_TEXT_MODEL_IDS,
23
+ VOICE_STS_MODEL_IDS,
24
+ VOICE_TTS_MODELS,
25
+ VOICE_TTS_MODEL_IDS,
10
26
  composeAgentPrompt,
11
27
  extractBasePrompt,
28
+ getVoiceOp,
29
+ getVoiceTtsModel,
30
+ isModelRelatedTtsFailure,
31
+ parseVoiceOpForm,
32
+ parseVoiceOpJsonBody,
12
33
  resolveConvaiTtsModel,
13
- stripMemoryBlock
14
- } from "./chunk-B4JC3DK2.js";
34
+ resolveConvaiTtsModelDetailed,
35
+ stripMemoryBlock,
36
+ voiceOpCredentialError,
37
+ voiceOpForwardPath,
38
+ voiceOpIsMultipart,
39
+ voiceOpPathParams,
40
+ voiceOpReturnsAudio,
41
+ voiceOpUpstreamBody,
42
+ voiceOpUpstreamPath
43
+ } from "./chunk-XE4LLC7Z.js";
15
44
  import {
16
45
  AUDIO_TAGS,
17
46
  AUDIO_TAG_GROUPS,
@@ -701,6 +730,10 @@ export {
701
730
  DEFAULT_ELEVENLABS_BASE_URL,
702
731
  DEFAULT_MEMORY_BLOCK,
703
732
  DEFAULT_MUSIC_MODEL,
733
+ DEFAULT_SOUND_GENERATION_MODEL,
734
+ DEFAULT_SPEECH_TO_TEXT_MODEL,
735
+ DEFAULT_STS_MODEL,
736
+ DEFAULT_TTS_MODEL,
704
737
  DEFAULT_TWILIO_BASE_URL,
705
738
  DEFAULT_VOICE_SETTINGS,
706
739
  DirectTelephonyClient,
@@ -711,27 +744,50 @@ export {
711
744
  ElevenLabsClient,
712
745
  HostedRuntimeTokenClient,
713
746
  HostedTelephonyClient,
747
+ LiveSession,
714
748
  MEMORY_CLIENT_TOOLS,
715
749
  MockTelephonyClient,
750
+ ShogoLiveClient,
751
+ TTS_FALLBACK_MODEL,
716
752
  TelephonyApiError,
717
753
  TelephonyConfigError,
718
754
  TwilioApiError,
719
755
  TwilioClient,
756
+ VOICE_OPS,
757
+ VOICE_OP_IDS,
758
+ VOICE_SOUND_GENERATION_MODEL_IDS,
759
+ VOICE_SPEECH_TO_TEXT_MODEL_IDS,
760
+ VOICE_STS_MODEL_IDS,
761
+ VOICE_TTS_MODELS,
762
+ VOICE_TTS_MODEL_IDS,
720
763
  buildPreviewLine,
721
764
  composeAgentPrompt,
722
765
  composeExpressivityBlock,
723
766
  createTelephonyClient,
724
767
  extractBasePrompt,
768
+ getVoiceOp,
769
+ getVoiceTtsModel,
770
+ isModelRelatedTtsFailure,
725
771
  isVoiceMockEnv,
726
772
  normalizeAudioTags,
727
773
  normalizeExpressivity,
728
774
  normalizeVoiceSettings,
775
+ parseVoiceOpForm,
776
+ parseVoiceOpJsonBody,
729
777
  readAudioTags,
730
778
  readExpressivity,
731
779
  readVoiceSettings,
732
780
  resolveConvaiTtsModel,
781
+ resolveConvaiTtsModelDetailed,
733
782
  stripAudioTags,
734
783
  stripExpressivityBlock,
735
- stripMemoryBlock
784
+ stripMemoryBlock,
785
+ voiceOpCredentialError,
786
+ voiceOpForwardPath,
787
+ voiceOpIsMultipart,
788
+ voiceOpPathParams,
789
+ voiceOpReturnsAudio,
790
+ voiceOpUpstreamBody,
791
+ voiceOpUpstreamPath
736
792
  };
737
793
  //# sourceMappingURL=index.js.map
@@ -0,0 +1,173 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/live/client.ts
21
+ var client_exports = {};
22
+ __export(client_exports, {
23
+ LiveSession: () => LiveSession,
24
+ ShogoLiveClient: () => ShogoLiveClient
25
+ });
26
+ module.exports = __toCommonJS(client_exports);
27
+ function encodeAudio(audio) {
28
+ if (typeof btoa === "function") {
29
+ let binary = "";
30
+ for (let i = 0; i < audio.length; i += 32768) {
31
+ binary += String.fromCharCode(...audio.subarray(i, i + 32768));
32
+ }
33
+ return btoa(binary);
34
+ }
35
+ const BufferImpl = globalThis.Buffer;
36
+ if (BufferImpl) return BufferImpl.from(audio).toString("base64");
37
+ throw new Error("Base64 encoding is unavailable in this runtime");
38
+ }
39
+ function normalizeBaseUrl(value) {
40
+ return value.replace(/\/+$/, "");
41
+ }
42
+ var LiveSession = class {
43
+ constructor(socket, initialSession) {
44
+ this.socket = socket;
45
+ this.initialSession = initialSession;
46
+ this.handlers = /* @__PURE__ */ new Map();
47
+ this.closed = false;
48
+ this.latestUsageSeconds = 0;
49
+ this.startedPromise = new Promise((resolve, reject) => {
50
+ this.resolveStarted = resolve;
51
+ this.rejectStarted = reject;
52
+ });
53
+ this.started = this.startedPromise;
54
+ this.closedPromise = new Promise((resolve) => {
55
+ this.resolveClosed = resolve;
56
+ });
57
+ socket.addEventListener("message", (message) => {
58
+ const raw = typeof message.data === "string" ? message.data : "";
59
+ if (!raw) return;
60
+ let event;
61
+ try {
62
+ event = JSON.parse(raw);
63
+ } catch {
64
+ return;
65
+ }
66
+ if (event.type === "session.started") this.resolveStarted(event);
67
+ if (event.type === "session.usage.updated") {
68
+ const seconds = event.usage?.seconds;
69
+ if (typeof seconds === "number") this.latestUsageSeconds = seconds;
70
+ }
71
+ if (event.type === "session.closed") {
72
+ this.closed = true;
73
+ this.resolveClosed(event);
74
+ }
75
+ if (event.type === "error" && !this.closed) {
76
+ const messageText = String(event.error?.message || "Live session error");
77
+ this.rejectStarted(new Error(messageText));
78
+ }
79
+ for (const handler of this.handlers.get(String(event.type)) ?? []) handler(event);
80
+ for (const handler of this.handlers.get("*") ?? []) handler(event);
81
+ });
82
+ socket.addEventListener("close", () => {
83
+ if (!this.closed) this.resolveClosed();
84
+ });
85
+ socket.addEventListener("error", () => {
86
+ if (!this.closed) this.rejectStarted(new Error("Live session WebSocket error"));
87
+ });
88
+ socket.addEventListener("open", () => {
89
+ if (initialSession) this.send({ type: "session.start", session: initialSession });
90
+ });
91
+ }
92
+ on(eventType, handler) {
93
+ const handlers = this.handlers.get(eventType) ?? /* @__PURE__ */ new Set();
94
+ handlers.add(handler);
95
+ this.handlers.set(eventType, handlers);
96
+ return () => handlers.delete(handler);
97
+ }
98
+ send(event) {
99
+ if (this.closed) throw new Error("Live session is closed");
100
+ this.socket.send(JSON.stringify(event));
101
+ }
102
+ appendAudio(audio) {
103
+ this.send({
104
+ type: "session.input_audio.append",
105
+ audio: typeof audio === "string" ? audio : encodeAudio(audio)
106
+ });
107
+ }
108
+ async close(timeoutMs = 15e3) {
109
+ if (this.closed) return;
110
+ if (this.socket.readyState === 1) this.send({ type: "session.close" });
111
+ const timeout = new Promise((resolve) => setTimeout(resolve, timeoutMs));
112
+ const result = await Promise.race([this.closedPromise, timeout]);
113
+ if (!this.closed) this.socket.close();
114
+ return result;
115
+ }
116
+ };
117
+ var ShogoLiveClient = class {
118
+ constructor(options) {
119
+ if (!!options.apiKey === !!options.runtimeToken) {
120
+ throw new Error("ShogoLiveClient requires exactly one of apiKey or runtimeToken.");
121
+ }
122
+ this.apiUrl = normalizeBaseUrl(options.apiUrl);
123
+ this.token = options.apiKey ?? options.runtimeToken;
124
+ this.fetchImpl = options.fetch ?? globalThis.fetch;
125
+ this.WebSocketImpl = options.WebSocket ?? globalThis.WebSocket;
126
+ if (typeof this.fetchImpl !== "function") throw new Error("fetch is unavailable");
127
+ if (typeof this.WebSocketImpl !== "function") throw new Error("WebSocket is unavailable");
128
+ }
129
+ httpUrl(path) {
130
+ return `${this.apiUrl}${path}`;
131
+ }
132
+ wsUrl(path) {
133
+ return this.httpUrl(path).replace(/^http/, "ws");
134
+ }
135
+ protocols() {
136
+ return ["shogo-live", `shogo-insecure-api-key.${this.token}`];
137
+ }
138
+ connect(session) {
139
+ const socket = new this.WebSocketImpl(this.wsUrl("/api/ai/v1/live/sessions"), this.protocols());
140
+ return new LiveSession(socket, session);
141
+ }
142
+ attach(sessionId) {
143
+ const socket = new this.WebSocketImpl(
144
+ this.wsUrl(`/api/ai/v1/live/sessions/${encodeURIComponent(sessionId)}/attach`),
145
+ this.protocols()
146
+ );
147
+ return new LiveSession(socket);
148
+ }
149
+ async createWebRtcSession(input) {
150
+ const response = await this.fetchImpl(this.httpUrl("/api/ai/v1/live/sessions"), {
151
+ method: "POST",
152
+ headers: {
153
+ Authorization: `Bearer ${this.token}`,
154
+ "Content-Type": "application/json"
155
+ },
156
+ body: JSON.stringify({
157
+ session: input.session,
158
+ transport: { type: "webrtc", sdp: input.sdp }
159
+ })
160
+ });
161
+ const body = await response.json();
162
+ if (!response.ok) {
163
+ throw new Error(body?.error?.message || `Live session creation failed (${response.status})`);
164
+ }
165
+ return body;
166
+ }
167
+ };
168
+ // Annotate the CommonJS export names for ESM import in node:
169
+ 0 && (module.exports = {
170
+ LiveSession,
171
+ ShogoLiveClient
172
+ });
173
+ //# sourceMappingURL=client.cjs.map