@effect-uai/elevenlabs 0.4.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.
Files changed (51) hide show
  1. package/LICENSE +21 -0
  2. package/dist/ElevenLabsSynthesizer.d.mts +58 -0
  3. package/dist/ElevenLabsSynthesizer.d.mts.map +1 -0
  4. package/dist/ElevenLabsSynthesizer.mjs +82 -0
  5. package/dist/ElevenLabsSynthesizer.mjs.map +1 -0
  6. package/dist/ElevenLabsSynthesizer.test.d.mts +1 -0
  7. package/dist/ElevenLabsSynthesizer.test.mjs +32 -0
  8. package/dist/ElevenLabsSynthesizer.test.mjs.map +1 -0
  9. package/dist/ElevenLabsTranscriber.d.mts +57 -0
  10. package/dist/ElevenLabsTranscriber.d.mts.map +1 -0
  11. package/dist/ElevenLabsTranscriber.mjs +97 -0
  12. package/dist/ElevenLabsTranscriber.mjs.map +1 -0
  13. package/dist/ElevenLabsTranscriber.test.d.mts +1 -0
  14. package/dist/ElevenLabsTranscriber.test.mjs +58 -0
  15. package/dist/ElevenLabsTranscriber.test.mjs.map +1 -0
  16. package/dist/chunk-uyGKjUfl.mjs +14 -0
  17. package/dist/codec.d.mts +43 -0
  18. package/dist/codec.d.mts.map +1 -0
  19. package/dist/codec.mjs +120 -0
  20. package/dist/codec.mjs.map +1 -0
  21. package/dist/codec.test.d.mts +1 -0
  22. package/dist/codec.test.mjs +142 -0
  23. package/dist/codec.test.mjs.map +1 -0
  24. package/dist/dist-DMsg8YLb.mjs +13782 -0
  25. package/dist/dist-DMsg8YLb.mjs.map +1 -0
  26. package/dist/index.d.mts +5 -0
  27. package/dist/index.mjs +5 -0
  28. package/dist/magic-string.es-CaWgF-3p.mjs +1013 -0
  29. package/dist/magic-string.es-CaWgF-3p.mjs.map +1 -0
  30. package/dist/models.d.mts +37 -0
  31. package/dist/models.d.mts.map +1 -0
  32. package/dist/models.mjs +1 -0
  33. package/dist/realtimeStt.d.mts +67 -0
  34. package/dist/realtimeStt.d.mts.map +1 -0
  35. package/dist/realtimeStt.mjs +163 -0
  36. package/dist/realtimeStt.mjs.map +1 -0
  37. package/dist/realtimeTts.d.mts +31 -0
  38. package/dist/realtimeTts.d.mts.map +1 -0
  39. package/dist/realtimeTts.mjs +77 -0
  40. package/dist/realtimeTts.mjs.map +1 -0
  41. package/package.json +64 -0
  42. package/src/ElevenLabsSynthesizer.test.ts +49 -0
  43. package/src/ElevenLabsSynthesizer.ts +165 -0
  44. package/src/ElevenLabsTranscriber.test.ts +63 -0
  45. package/src/ElevenLabsTranscriber.ts +179 -0
  46. package/src/codec.test.ts +128 -0
  47. package/src/codec.ts +185 -0
  48. package/src/index.ts +4 -0
  49. package/src/models.ts +46 -0
  50. package/src/realtimeStt.ts +273 -0
  51. package/src/realtimeTts.ts +147 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Betalyra Sociedade Unipessoal Lda.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,58 @@
1
+ import { VoiceSettings } from "./codec.mjs";
2
+ import { ElevenLabsTtsModel, ElevenLabsVoiceId } from "./models.mjs";
3
+ import { Context, Effect, Layer, Redacted, Stream } from "effect";
4
+ import { HttpClient } from "effect/unstable/http";
5
+ import * as Socket from "effect/unstable/socket/Socket";
6
+ import { CommonStreamSynthesizeRequest, CommonSynthesizeRequest, SpeechSynthesizer, SpeechSynthesizerService, TtsIncrementalText } from "@effect-uai/core/SpeechSynthesizer";
7
+ import * as AiError from "@effect-uai/core/AiError";
8
+ import * as _$_effect_uai_core_Audio0 from "@effect-uai/core/Audio";
9
+ import { AudioBlob, AudioChunk } from "@effect-uai/core/Audio";
10
+
11
+ //#region src/ElevenLabsSynthesizer.d.ts
12
+ declare namespace ElevenLabsSynthesizer_d_exports {
13
+ export { Config, ElevenLabsSynthesizeRequest, ElevenLabsSynthesizer, ElevenLabsSynthesizerService, layer, make };
14
+ }
15
+ /**
16
+ * ElevenLabs-typed synthesize request. `voiceSettings` exposes the
17
+ * provider's prosody/timbre controls; `seed` makes generation
18
+ * deterministic; `previousText` / `nextText` thread context across
19
+ * sequential calls for natural prosody.
20
+ */
21
+ type ElevenLabsSynthesizeRequest = Omit<CommonSynthesizeRequest, "model" | "voiceId"> & {
22
+ readonly model: ElevenLabsTtsModel;
23
+ readonly voiceId: ElevenLabsVoiceId;
24
+ readonly voiceSettings?: VoiceSettings;
25
+ readonly seed?: number;
26
+ readonly previousText?: string;
27
+ readonly nextText?: string;
28
+ };
29
+ type ElevenLabsSynthesizerService = {
30
+ readonly synthesize: (r: ElevenLabsSynthesizeRequest) => Effect.Effect<AudioBlob, AiError.AiError>;
31
+ readonly streamSynthesis: (r: ElevenLabsSynthesizeRequest) => Stream.Stream<AudioChunk, AiError.AiError>;
32
+ readonly streamSynthesisFrom: SpeechSynthesizerService["streamSynthesisFrom"];
33
+ };
34
+ declare const ElevenLabsSynthesizer_base: Context.ServiceClass<ElevenLabsSynthesizer, "@betalyra/effect-uai/providers/elevenlabs/ElevenLabsSynthesizer", ElevenLabsSynthesizerService>;
35
+ declare class ElevenLabsSynthesizer extends ElevenLabsSynthesizer_base {}
36
+ type Config = {
37
+ readonly apiKey: Redacted.Redacted;
38
+ readonly baseUrl?: string;
39
+ };
40
+ declare const make: (cfg: Config) => Effect.Effect<{
41
+ synthesize: (r: ElevenLabsSynthesizeRequest) => Effect.Effect<{
42
+ format: _$_effect_uai_core_Audio0.AudioFormat;
43
+ bytes: Uint8Array<ArrayBuffer>;
44
+ }, AiError.AiError, never>;
45
+ streamSynthesis: (r: ElevenLabsSynthesizeRequest) => Stream.Stream<AudioChunk, AiError.AiError, never>;
46
+ streamSynthesisFrom: <E, R>(textIn: Stream.Stream<string, E, R>, request: CommonStreamSynthesizeRequest) => Stream.Stream<AudioChunk, AiError.AiError | E, Exclude<R, Socket.WebSocketConstructor>>;
47
+ }, never, HttpClient.HttpClient | Socket.WebSocketConstructor>;
48
+ /**
49
+ * Layer registers `ElevenLabsSynthesizer`, the generic
50
+ * `SpeechSynthesizer`, **and `TtsIncrementalText`** — incremental
51
+ * text-in is wired to the realtime `/stream-input` WebSocket. Provide
52
+ * `Socket.layerWebSocketConstructorGlobal` and an `HttpClient` Layer at
53
+ * the call site.
54
+ */
55
+ declare const layer: (cfg: Config) => Layer.Layer<ElevenLabsSynthesizer | SpeechSynthesizer | TtsIncrementalText, never, HttpClient.HttpClient | Socket.WebSocketConstructor>;
56
+ //#endregion
57
+ export { Config, ElevenLabsSynthesizeRequest, ElevenLabsSynthesizer, ElevenLabsSynthesizerService, layer, make, ElevenLabsSynthesizer_d_exports as t };
58
+ //# sourceMappingURL=ElevenLabsSynthesizer.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ElevenLabsSynthesizer.d.mts","names":[],"sources":["../src/ElevenLabsSynthesizer.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;KAiCY,2BAAA,GAA8B,IAAA,CAAK,uBAAA;EAAA,SACpC,KAAA,EAAO,kBAAA;EAAA,SACP,OAAA,EAAS,iBAAA;EAAA,SACT,aAAA,GAAgB,aAAA;EAAA,SAChB,IAAA;EAAA,SACA,YAAA;EAAA,SACA,QAAA;AAAA;AAAA,KAGC,4BAAA;EAAA,SACD,UAAA,GAAa,CAAA,EAAG,2BAAA,KAAgC,MAAA,CAAO,MAAA,CAAO,SAAA,EAAW,OAAA,CAAQ,OAAA;EAAA,SACjF,eAAA,GACP,CAAA,EAAG,2BAAA,KACA,MAAA,CAAO,MAAA,CAAO,UAAA,EAAY,OAAA,CAAQ,OAAA;EAAA,SAC9B,mBAAA,EAAqB,wBAAA;AAAA;AAAA,cAC/B,0BAAA;cAEY,qBAAA,SAA8B,0BAAA;AAAA,KAK/B,MAAA;EAAA,SAAoB,MAAA,EAAQ,QAAA,CAAS,QAAA;EAAA,SAAmB,OAAA;AAAA;AAAA,cAoEvD,IAAA,GAAQ,GAAA,EAAK,MAAA,KAAM,MAAA,CAAA,MAAA;;;;;;;;;AAjFhC;;;;;;cAwGa,KAAA,GAAS,GAAA,EAAK,MAAA,KAAM,KAAA,CAAA,KAAA,CAAA,qBAAA,GAAA,iBAAA,GAAA,kBAAA,SAAA,UAAA,CAAA,UAAA,GAAA,MAAA,CAAA,oBAAA"}
@@ -0,0 +1,82 @@
1
+ import { n as __exportAll } from "./chunk-uyGKjUfl.mjs";
2
+ import { defaultFormat, formatToOutputSlug, httpStatusError, transportFailure, wireVoiceSettings } from "./codec.mjs";
3
+ import { streamSynthesis } from "./realtimeTts.mjs";
4
+ import { Context, Effect, Layer, Redacted, Stream } from "effect";
5
+ import { HttpClient, HttpClientRequest } from "effect/unstable/http";
6
+ import * as Socket from "effect/unstable/socket/Socket";
7
+ import { SpeechSynthesizer, TtsIncrementalText } from "@effect-uai/core/SpeechSynthesizer";
8
+ //#region src/ElevenLabsSynthesizer.ts
9
+ var ElevenLabsSynthesizer_exports = /* @__PURE__ */ __exportAll({
10
+ ElevenLabsSynthesizer: () => ElevenLabsSynthesizer,
11
+ layer: () => layer,
12
+ make: () => make
13
+ });
14
+ var ElevenLabsSynthesizer = class extends Context.Service()("@betalyra/effect-uai/providers/elevenlabs/ElevenLabsSynthesizer") {};
15
+ const buildBody = (r) => ({
16
+ text: r.text,
17
+ model_id: r.model,
18
+ ...r.languageCode !== void 0 && { language_code: r.languageCode },
19
+ ...r.seed !== void 0 && { seed: r.seed },
20
+ ...r.previousText !== void 0 && { previous_text: r.previousText },
21
+ ...r.nextText !== void 0 && { next_text: r.nextText },
22
+ ...r.voiceSettings !== void 0 && { voice_settings: wireVoiceSettings(r.voiceSettings) }
23
+ });
24
+ const baseUrl = (cfg) => cfg.baseUrl ?? "https://api.elevenlabs.io/v1";
25
+ const buildHttpRequest = (cfg, r, path) => Effect.gen(function* () {
26
+ const format = r.outputFormat ?? defaultFormat;
27
+ const slug = yield* formatToOutputSlug(format);
28
+ const url = `${baseUrl(cfg)}/text-to-speech/${r.voiceId}${path}?output_format=${slug}`;
29
+ return {
30
+ httpRequest: HttpClientRequest.post(url).pipe(HttpClientRequest.setHeader("xi-api-key", Redacted.value(cfg.apiKey)), HttpClientRequest.bodyJsonUnsafe(buildBody(r))),
31
+ format
32
+ };
33
+ });
34
+ const synthesizeImpl = (cfg) => (request) => Effect.gen(function* () {
35
+ const client = yield* HttpClient.HttpClient;
36
+ const { httpRequest, format } = yield* buildHttpRequest(cfg, request, "");
37
+ const response = yield* client.execute(httpRequest).pipe(Effect.mapError(transportFailure));
38
+ if (response.status >= 400) {
39
+ const text = yield* response.text.pipe(Effect.orElseSucceed(() => ""));
40
+ return yield* Effect.fail(httpStatusError(response.status, text));
41
+ }
42
+ const bytes = yield* response.arrayBuffer.pipe(Effect.mapError(transportFailure));
43
+ return {
44
+ format,
45
+ bytes: new Uint8Array(bytes)
46
+ };
47
+ });
48
+ const streamSynthesisImpl = (cfg) => (request) => Stream.unwrap(Effect.gen(function* () {
49
+ const client = yield* HttpClient.HttpClient;
50
+ const { httpRequest } = yield* buildHttpRequest(cfg, request, "/stream");
51
+ const response = yield* client.execute(httpRequest).pipe(Effect.mapError(transportFailure));
52
+ if (response.status >= 400) {
53
+ const text = yield* response.text.pipe(Effect.orElseSucceed(() => ""));
54
+ return Stream.fail(httpStatusError(response.status, text));
55
+ }
56
+ return response.stream.pipe(Stream.mapError(transportFailure), Stream.map((bytes) => ({ bytes })));
57
+ }));
58
+ const make = (cfg) => Effect.gen(function* () {
59
+ const client = yield* HttpClient.HttpClient;
60
+ const ctor = yield* Socket.WebSocketConstructor;
61
+ return {
62
+ synthesize: (r) => synthesizeImpl(cfg)(r).pipe(Effect.provideService(HttpClient.HttpClient, client)),
63
+ streamSynthesis: (r) => streamSynthesisImpl(cfg)(r).pipe(Stream.provideService(HttpClient.HttpClient, client)),
64
+ streamSynthesisFrom: (textIn, request) => streamSynthesis(cfg)(textIn, request).pipe(Stream.provideService(Socket.WebSocketConstructor, ctor))
65
+ };
66
+ });
67
+ /**
68
+ * Layer registers `ElevenLabsSynthesizer`, the generic
69
+ * `SpeechSynthesizer`, **and `TtsIncrementalText`** — incremental
70
+ * text-in is wired to the realtime `/stream-input` WebSocket. Provide
71
+ * `Socket.layerWebSocketConstructorGlobal` and an `HttpClient` Layer at
72
+ * the call site.
73
+ */
74
+ const layer = (cfg) => Layer.mergeAll(Layer.effect(ElevenLabsSynthesizer, make(cfg)), Layer.effect(SpeechSynthesizer, Effect.map(make(cfg), (s) => ({
75
+ synthesize: (req) => s.synthesize(req),
76
+ streamSynthesis: (req) => s.streamSynthesis(req),
77
+ streamSynthesisFrom: (textIn, req) => s.streamSynthesisFrom(textIn, req)
78
+ }))), Layer.succeed(TtsIncrementalText, void 0));
79
+ //#endregion
80
+ export { ElevenLabsSynthesizer, layer, make, ElevenLabsSynthesizer_exports as t };
81
+
82
+ //# sourceMappingURL=ElevenLabsSynthesizer.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ElevenLabsSynthesizer.mjs","names":["realtimeStream"],"sources":["../src/ElevenLabsSynthesizer.ts"],"sourcesContent":["import { Context, Effect, Layer, Redacted, Stream } from \"effect\"\nimport { HttpClient, HttpClientRequest } from \"effect/unstable/http\"\nimport * as Socket from \"effect/unstable/socket/Socket\"\nimport type * as AiError from \"@effect-uai/core/AiError\"\nimport type { AudioBlob, AudioChunk } from \"@effect-uai/core/Audio\"\nimport {\n type CommonStreamSynthesizeRequest,\n type CommonSynthesizeRequest,\n SpeechSynthesizer,\n type SpeechSynthesizerService,\n TtsIncrementalText,\n} from \"@effect-uai/core/SpeechSynthesizer\"\nimport {\n defaultFormat,\n formatToOutputSlug,\n httpStatusError,\n transportFailure,\n type VoiceSettings,\n wireVoiceSettings,\n} from \"./codec.js\"\nimport type { ElevenLabsTtsModel, ElevenLabsVoiceId } from \"./models.js\"\nimport { streamSynthesis as realtimeStream } from \"./realtimeTts.js\"\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\n/**\n * ElevenLabs-typed synthesize request. `voiceSettings` exposes the\n * provider's prosody/timbre controls; `seed` makes generation\n * deterministic; `previousText` / `nextText` thread context across\n * sequential calls for natural prosody.\n */\nexport type ElevenLabsSynthesizeRequest = Omit<CommonSynthesizeRequest, \"model\" | \"voiceId\"> & {\n readonly model: ElevenLabsTtsModel\n readonly voiceId: ElevenLabsVoiceId\n readonly voiceSettings?: VoiceSettings\n readonly seed?: number\n readonly previousText?: string\n readonly nextText?: string\n}\n\nexport type ElevenLabsSynthesizerService = {\n readonly synthesize: (r: ElevenLabsSynthesizeRequest) => Effect.Effect<AudioBlob, AiError.AiError>\n readonly streamSynthesis: (\n r: ElevenLabsSynthesizeRequest,\n ) => Stream.Stream<AudioChunk, AiError.AiError>\n readonly streamSynthesisFrom: SpeechSynthesizerService[\"streamSynthesisFrom\"]\n}\n\nexport class ElevenLabsSynthesizer extends Context.Service<\n ElevenLabsSynthesizer,\n ElevenLabsSynthesizerService\n>()(\"@betalyra/effect-uai/providers/elevenlabs/ElevenLabsSynthesizer\") {}\n\nexport type Config = { readonly apiKey: Redacted.Redacted; readonly baseUrl?: string }\n\n// ---------------------------------------------------------------------------\n// Codec — request → JSON body\n// ---------------------------------------------------------------------------\n\nconst buildBody = (r: ElevenLabsSynthesizeRequest) => ({\n text: r.text,\n model_id: r.model,\n ...(r.languageCode !== undefined && { language_code: r.languageCode }),\n ...(r.seed !== undefined && { seed: r.seed }),\n ...(r.previousText !== undefined && { previous_text: r.previousText }),\n ...(r.nextText !== undefined && { next_text: r.nextText }),\n ...(r.voiceSettings !== undefined && { voice_settings: wireVoiceSettings(r.voiceSettings) }),\n})\n\n// ---------------------------------------------------------------------------\n// HTTP plumbing (sync + chunked-HTTP streaming)\n// ---------------------------------------------------------------------------\n\nconst baseUrl = (cfg: Config) => cfg.baseUrl ?? \"https://api.elevenlabs.io/v1\"\n\nconst buildHttpRequest = (cfg: Config, r: ElevenLabsSynthesizeRequest, path: \"\" | \"/stream\") =>\n Effect.gen(function* () {\n const format = r.outputFormat ?? defaultFormat\n const slug = yield* formatToOutputSlug(format)\n const url = `${baseUrl(cfg)}/text-to-speech/${r.voiceId}${path}?output_format=${slug}`\n const httpRequest = HttpClientRequest.post(url).pipe(\n HttpClientRequest.setHeader(\"xi-api-key\", Redacted.value(cfg.apiKey)),\n HttpClientRequest.bodyJsonUnsafe(buildBody(r)),\n )\n return { httpRequest, format }\n })\n\nconst synthesizeImpl = (cfg: Config) => (request: ElevenLabsSynthesizeRequest) =>\n Effect.gen(function* () {\n const client = yield* HttpClient.HttpClient\n const { httpRequest, format } = yield* buildHttpRequest(cfg, request, \"\")\n const response = yield* client.execute(httpRequest).pipe(Effect.mapError(transportFailure))\n if (response.status >= 400) {\n const text = yield* response.text.pipe(Effect.orElseSucceed(() => \"\"))\n return yield* Effect.fail(httpStatusError(response.status, text))\n }\n const bytes = yield* response.arrayBuffer.pipe(Effect.mapError(transportFailure))\n return { format, bytes: new Uint8Array(bytes) } satisfies AudioBlob\n })\n\nconst streamSynthesisImpl = (cfg: Config) => (request: ElevenLabsSynthesizeRequest) =>\n Stream.unwrap(\n Effect.gen(function* () {\n const client = yield* HttpClient.HttpClient\n const { httpRequest } = yield* buildHttpRequest(cfg, request, \"/stream\")\n const response = yield* client.execute(httpRequest).pipe(Effect.mapError(transportFailure))\n if (response.status >= 400) {\n const text = yield* response.text.pipe(Effect.orElseSucceed(() => \"\"))\n return Stream.fail(httpStatusError(response.status, text))\n }\n return response.stream.pipe(\n Stream.mapError(transportFailure),\n Stream.map((bytes): AudioChunk => ({ bytes })),\n )\n }),\n )\n\n// ---------------------------------------------------------------------------\n// Constructors\n// ---------------------------------------------------------------------------\n\nexport const make = (cfg: Config) =>\n Effect.gen(function* () {\n const client = yield* HttpClient.HttpClient\n const ctor = yield* Socket.WebSocketConstructor\n return {\n synthesize: (r) =>\n synthesizeImpl(cfg)(r).pipe(Effect.provideService(HttpClient.HttpClient, client)),\n streamSynthesis: (r) =>\n streamSynthesisImpl(cfg)(r).pipe(Stream.provideService(HttpClient.HttpClient, client)),\n streamSynthesisFrom: (textIn, request) =>\n realtimeStream(cfg)(textIn, request as ElevenLabsSynthesizeRequest).pipe(\n Stream.provideService(Socket.WebSocketConstructor, ctor),\n ),\n } satisfies ElevenLabsSynthesizerService\n })\n\n/**\n * Layer registers `ElevenLabsSynthesizer`, the generic\n * `SpeechSynthesizer`, **and `TtsIncrementalText`** — incremental\n * text-in is wired to the realtime `/stream-input` WebSocket. Provide\n * `Socket.layerWebSocketConstructorGlobal` and an `HttpClient` Layer at\n * the call site.\n */\nexport const layer = (cfg: Config) =>\n Layer.mergeAll(\n Layer.effect(ElevenLabsSynthesizer, make(cfg)),\n Layer.effect(\n SpeechSynthesizer,\n Effect.map(\n make(cfg),\n (s): SpeechSynthesizerService => ({\n synthesize: (req: CommonSynthesizeRequest) =>\n s.synthesize(req as ElevenLabsSynthesizeRequest),\n streamSynthesis: (req: CommonSynthesizeRequest) =>\n s.streamSynthesis(req as ElevenLabsSynthesizeRequest),\n streamSynthesisFrom: (textIn, req: CommonStreamSynthesizeRequest) =>\n s.streamSynthesisFrom(textIn, req),\n }),\n ),\n ),\n Layer.succeed(TtsIncrementalText, undefined),\n )\n"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export { };
@@ -0,0 +1,32 @@
1
+ import { i as it, n as globalExpect, r as describe, t as import_dist } from "./dist-DMsg8YLb.mjs";
2
+ import { layer } from "./ElevenLabsSynthesizer.mjs";
3
+ import { Effect, Layer, Redacted, Stream } from "effect";
4
+ import { FetchHttpClient } from "effect/unstable/http";
5
+ import * as Socket from "effect/unstable/socket/Socket";
6
+ import * as SpeechSynthesizer$1 from "@effect-uai/core/SpeechSynthesizer";
7
+ const live = layer({ apiKey: Redacted.make("test-key") }).pipe(Layer.provide(FetchHttpClient.layer), Layer.provide(Socket.layerWebSocketConstructorGlobal));
8
+ describe("ElevenLabsSynthesizer Layer (compile-time)", () => {
9
+ it("registers `TtsIncrementalText` — `streamSynthesisFrom` clears R to never", () => {
10
+ const audio = Stream.fromIterable(["hello ", "world"]).pipe(SpeechSynthesizer$1.streamSynthesisFrom({
11
+ model: "eleven_flash_v2_5",
12
+ voiceId: "JBFqnCBsd6RMkjVDRZzb"
13
+ }));
14
+ (0, import_dist.expectTypeOf)(Stream.runDrain(audio).pipe(Effect.provide(live))).toEqualTypeOf();
15
+ });
16
+ it("sync `synthesize` and chunked `streamSynthesis` require no marker", () => {
17
+ (0, import_dist.expectTypeOf)(SpeechSynthesizer$1.synthesize({
18
+ text: "hi",
19
+ model: "eleven_multilingual_v2",
20
+ voiceId: "JBFqnCBsd6RMkjVDRZzb"
21
+ }).pipe(Effect.provide(live))).toEqualTypeOf();
22
+ globalExpect(Stream.runCollect(SpeechSynthesizer$1.streamSynthesis({
23
+ text: "hi",
24
+ model: "eleven_multilingual_v2",
25
+ voiceId: "JBFqnCBsd6RMkjVDRZzb"
26
+ })).pipe(Effect.provide(live))).toBeDefined();
27
+ });
28
+ });
29
+ //#endregion
30
+ export {};
31
+
32
+ //# sourceMappingURL=ElevenLabsSynthesizer.test.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ElevenLabsSynthesizer.test.mjs","names":["ElevenLabsSynthesizer.layer","SpeechSynthesizer"],"sources":["../src/ElevenLabsSynthesizer.test.ts"],"sourcesContent":["import { Effect, Layer, Redacted, Stream } from \"effect\"\nimport { FetchHttpClient } from \"effect/unstable/http\"\nimport * as Socket from \"effect/unstable/socket/Socket\"\nimport { describe, expect, expectTypeOf, it } from \"vitest\"\nimport type * as AiError from \"@effect-uai/core/AiError\"\nimport type { AudioBlob } from \"@effect-uai/core/Audio\"\nimport * as SpeechSynthesizer from \"@effect-uai/core/SpeechSynthesizer\"\nimport * as ElevenLabsSynthesizer from \"./ElevenLabsSynthesizer.js\"\n\nconst cfg: ElevenLabsSynthesizer.Config = { apiKey: Redacted.make(\"test-key\") }\n// FetchHttpClient + globalThis.WebSocket are required for `make`, but these\n// tests only exercise the codec and compile-time gating — no real network\n// call is made.\nconst live = ElevenLabsSynthesizer.layer(cfg).pipe(\n Layer.provide(FetchHttpClient.layer),\n Layer.provide(Socket.layerWebSocketConstructorGlobal),\n)\n\ndescribe(\"ElevenLabsSynthesizer Layer (compile-time)\", () => {\n it(\"registers `TtsIncrementalText` — `streamSynthesisFrom` clears R to never\", () => {\n const tokens: Stream.Stream<string> = Stream.fromIterable([\"hello \", \"world\"])\n const audio = tokens.pipe(\n SpeechSynthesizer.streamSynthesisFrom({\n model: \"eleven_flash_v2_5\",\n voiceId: \"JBFqnCBsd6RMkjVDRZzb\",\n }),\n )\n const program = Stream.runDrain(audio).pipe(Effect.provide(live))\n expectTypeOf(program).toEqualTypeOf<Effect.Effect<void, AiError.AiError, never>>()\n })\n\n it(\"sync `synthesize` and chunked `streamSynthesis` require no marker\", () => {\n const synth = SpeechSynthesizer.synthesize({\n text: \"hi\",\n model: \"eleven_multilingual_v2\",\n voiceId: \"JBFqnCBsd6RMkjVDRZzb\",\n }).pipe(Effect.provide(live))\n expectTypeOf(synth).toEqualTypeOf<Effect.Effect<AudioBlob, AiError.AiError, never>>()\n\n const _stream = Stream.runCollect(\n SpeechSynthesizer.streamSynthesis({\n text: \"hi\",\n model: \"eleven_multilingual_v2\",\n voiceId: \"JBFqnCBsd6RMkjVDRZzb\",\n }),\n ).pipe(Effect.provide(live))\n expect(_stream).toBeDefined()\n })\n})\n"],"mappings":";;;;;;AAaA,MAAM,OAAOA,MAA4B,EAJG,QAAQ,SAAS,KAAK,WAAW,EAIpC,CAAI,CAAC,KAC5C,MAAM,QAAQ,gBAAgB,MAAM,EACpC,MAAM,QAAQ,OAAO,gCAAgC,CACtD;AAED,SAAS,oDAAoD;AAC3D,IAAG,kFAAkF;EAEnF,MAAM,QADgC,OAAO,aAAa,CAAC,UAAU,QAAQ,CACzD,CAAC,KACnBC,oBAAkB,oBAAoB;GACpC,OAAO;GACP,SAAS;GACV,CAAC,CACH;AAED,GAAA,GAAA,YAAA,cADgB,OAAO,SAAS,MAAM,CAAC,KAAK,OAAO,QAAQ,KAAK,CAC5C,CAAC,CAAC,eAA4D;GAClF;AAEF,IAAG,2EAA2E;AAM5E,GAAA,GAAA,YAAA,cALcA,oBAAkB,WAAW;GACzC,MAAM;GACN,OAAO;GACP,SAAS;GACV,CAAC,CAAC,KAAK,OAAO,QAAQ,KAAK,CACV,CAAC,CAAC,eAAiE;AASrF,eAPgB,OAAO,WACrBA,oBAAkB,gBAAgB;GAChC,MAAM;GACN,OAAO;GACP,SAAS;GACV,CAAC,CACH,CAAC,KAAK,OAAO,QAAQ,KAAK,CACb,CAAC,CAAC,aAAa;GAC7B;EACF"}
@@ -0,0 +1,57 @@
1
+ import { ElevenLabsSttModel } from "./models.mjs";
2
+ import { Context, Effect, Layer, Redacted, Schema, Stream } from "effect";
3
+ import { HttpClient } from "effect/unstable/http";
4
+ import * as Socket from "effect/unstable/socket/Socket";
5
+ import * as AiError from "@effect-uai/core/AiError";
6
+ import * as _$_effect_uai_core_Transcriber0 from "@effect-uai/core/Transcriber";
7
+ import { CommonTranscribeRequest, SttStreaming, Transcriber, TranscriberService } from "@effect-uai/core/Transcriber";
8
+ import * as _$_effect_uai_core_Transcript0 from "@effect-uai/core/Transcript";
9
+ import { TranscriptResult, WordTimestamp } from "@effect-uai/core/Transcript";
10
+
11
+ //#region src/ElevenLabsTranscriber.d.ts
12
+ declare namespace ElevenLabsTranscriber_d_exports {
13
+ export { Config, ElevenLabsTranscribeRequest, ElevenLabsTranscriber, ElevenLabsTranscriberService, layer, make };
14
+ }
15
+ /**
16
+ * ElevenLabs-typed transcribe request. `model` narrows to
17
+ * `ElevenLabsSttModel`. `numSpeakers` hints diarization. `audioEvents`
18
+ * surfaces `(laughter)` / `(music)` tags inline in `text` (provider
19
+ * default: true). `fileName` overrides the multipart upload's
20
+ * `filename`; ElevenLabs uses the extension to detect format.
21
+ */
22
+ type ElevenLabsTranscribeRequest = Omit<CommonTranscribeRequest, "model"> & {
23
+ readonly model: ElevenLabsSttModel;
24
+ readonly numSpeakers?: number;
25
+ readonly audioEvents?: boolean;
26
+ readonly fileName?: string;
27
+ };
28
+ type ElevenLabsTranscriberService = {
29
+ readonly transcribe: (r: ElevenLabsTranscribeRequest) => Effect.Effect<TranscriptResult, AiError.AiError>;
30
+ readonly streamTranscriptionFrom: TranscriberService["streamTranscriptionFrom"];
31
+ };
32
+ declare const ElevenLabsTranscriber_base: Context.ServiceClass<ElevenLabsTranscriber, "@betalyra/effect-uai/providers/elevenlabs/ElevenLabsTranscriber", ElevenLabsTranscriberService>;
33
+ declare class ElevenLabsTranscriber extends ElevenLabsTranscriber_base {}
34
+ type Config = {
35
+ readonly apiKey: Redacted.Redacted;
36
+ readonly baseUrl?: string;
37
+ };
38
+ declare const make: (cfg: Config) => Effect.Effect<{
39
+ transcribe: (r: ElevenLabsTranscribeRequest) => Effect.Effect<{
40
+ raw: Schema.Json;
41
+ words?: WordTimestamp[];
42
+ languageCode?: string;
43
+ text: string;
44
+ }, AiError.AiError, never>;
45
+ streamTranscriptionFrom: <E, R>(audioIn: Stream.Stream<Uint8Array<ArrayBufferLike>, E, R>, request: _$_effect_uai_core_Transcriber0.CommonStreamTranscribeRequest) => Stream.Stream<_$_effect_uai_core_Transcript0.TranscriptEvent, AiError.AiError | E, Exclude<Exclude<R, HttpClient.HttpClient>, Socket.WebSocketConstructor>>;
46
+ }, never, HttpClient.HttpClient | Socket.WebSocketConstructor>;
47
+ /**
48
+ * Layer registers `ElevenLabsTranscriber`, the generic `Transcriber`,
49
+ * **and the `SttStreaming` capability marker** — `streamTranscriptionFrom`
50
+ * is wired to the realtime WebSocket. Provide
51
+ * `Socket.layerWebSocketConstructorGlobal` (or a custom constructor) +
52
+ * an `HttpClient` Layer at the call site.
53
+ */
54
+ declare const layer: (cfg: Config) => Layer.Layer<ElevenLabsTranscriber | Transcriber | SttStreaming, never, HttpClient.HttpClient | Socket.WebSocketConstructor>;
55
+ //#endregion
56
+ export { Config, ElevenLabsTranscribeRequest, ElevenLabsTranscriber, ElevenLabsTranscriberService, layer, make, ElevenLabsTranscriber_d_exports as t };
57
+ //# sourceMappingURL=ElevenLabsTranscriber.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ElevenLabsTranscriber.d.mts","names":[],"sources":["../src/ElevenLabsTranscriber.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;KA0BY,2BAAA,GAA8B,IAAA,CAAK,uBAAA;EAAA,SACpC,KAAA,EAAO,kBAAA;EAAA,SACP,WAAA;EAAA,SACA,WAAA;EAAA,SACA,QAAA;AAAA;AAAA,KAGC,4BAAA;EAAA,SACD,UAAA,GACP,CAAA,EAAG,2BAAA,KACA,MAAA,CAAO,MAAA,CAAO,gBAAA,EAAkB,OAAA,CAAQ,OAAA;EAAA,SACpC,uBAAA,EAAyB,kBAAA;AAAA;AAAA,cACnC,0BAAA;cAEY,qBAAA,SAA8B,0BAAA;AAAA,KAK/B,MAAA;EAAA,SAAoB,MAAA,EAAQ,QAAA,CAAS,QAAA;EAAA,SAAmB,OAAA;AAAA;AAAA,cAgGvD,IAAA,GAAQ,GAAA,EAAK,MAAA,KAAM,MAAA,CAAA,MAAA;;;;;;;;;;;;;;;;cAsBnB,KAAA,GAAS,GAAA,EAAK,MAAA,KAAM,KAAA,CAAA,KAAA,CAAA,qBAAA,GAAA,WAAA,GAAA,YAAA,SAAA,UAAA,CAAA,UAAA,GAAA,MAAA,CAAA,oBAAA"}
@@ -0,0 +1,97 @@
1
+ import { n as __exportAll } from "./chunk-uyGKjUfl.mjs";
2
+ import { audioToBlob, defaultFileName, httpStatusError, transportFailure } from "./codec.mjs";
3
+ import { streamTranscription } from "./realtimeStt.mjs";
4
+ import { Context, Effect, Layer, Redacted, Schema, Stream } from "effect";
5
+ import { HttpClient, HttpClientRequest } from "effect/unstable/http";
6
+ import * as Socket from "effect/unstable/socket/Socket";
7
+ import * as AiError from "@effect-uai/core/AiError";
8
+ import { SttStreaming, Transcriber } from "@effect-uai/core/Transcriber";
9
+ //#region src/ElevenLabsTranscriber.ts
10
+ var ElevenLabsTranscriber_exports = /* @__PURE__ */ __exportAll({
11
+ ElevenLabsTranscriber: () => ElevenLabsTranscriber,
12
+ layer: () => layer,
13
+ make: () => make
14
+ });
15
+ var ElevenLabsTranscriber = class extends Context.Service()("@betalyra/effect-uai/providers/elevenlabs/ElevenLabsTranscriber") {};
16
+ const Word = Schema.Struct({
17
+ text: Schema.String,
18
+ start: Schema.optional(Schema.Number),
19
+ end: Schema.optional(Schema.Number),
20
+ type: Schema.optional(Schema.String),
21
+ speaker_id: Schema.optional(Schema.String),
22
+ logprob: Schema.optional(Schema.Number)
23
+ });
24
+ const Wire = Schema.Struct({
25
+ text: Schema.String,
26
+ language_code: Schema.optional(Schema.String),
27
+ language_probability: Schema.optional(Schema.Number),
28
+ words: Schema.optional(Schema.Array(Word)),
29
+ transcription_id: Schema.optional(Schema.String)
30
+ });
31
+ const decodeWire = Schema.decodeUnknownEffect(Wire);
32
+ const toWordTimestamp = (w) => w.start === void 0 || w.end === void 0 ? void 0 : {
33
+ text: w.text,
34
+ startSeconds: w.start,
35
+ endSeconds: w.end,
36
+ ...w.logprob !== void 0 && { confidence: Math.exp(w.logprob) },
37
+ ...w.speaker_id !== void 0 && { speakerId: w.speaker_id }
38
+ };
39
+ const buildForm = (request) => Effect.gen(function* () {
40
+ const blob = yield* audioToBlob(request.audio);
41
+ const fileName = request.fileName ?? defaultFileName(request.audio.mimeType ?? "");
42
+ const form = new FormData();
43
+ form.set("model_id", request.model);
44
+ form.set("file", blob, fileName);
45
+ if (request.language !== void 0) form.set("language_code", request.language);
46
+ if (request.diarization !== void 0) form.set("diarize", request.diarization ? "true" : "false");
47
+ if (request.wordTimestamps === true) form.set("timestamps_granularity", "word");
48
+ if (request.numSpeakers !== void 0) form.set("num_speakers", String(request.numSpeakers));
49
+ if (request.audioEvents !== void 0) form.set("tag_audio_events", request.audioEvents ? "true" : "false");
50
+ return form;
51
+ });
52
+ const baseUrl = (cfg) => cfg.baseUrl ?? "https://api.elevenlabs.io/v1";
53
+ const transcribeImpl = (cfg) => (request) => Effect.gen(function* () {
54
+ const client = yield* HttpClient.HttpClient;
55
+ const form = yield* buildForm(request);
56
+ const httpRequest = HttpClientRequest.post(`${baseUrl(cfg)}/speech-to-text`).pipe(HttpClientRequest.setHeader("xi-api-key", Redacted.value(cfg.apiKey)), HttpClientRequest.bodyFormData(form));
57
+ const response = yield* client.execute(httpRequest).pipe(Effect.mapError(transportFailure));
58
+ if (response.status >= 400) {
59
+ const text = yield* response.text.pipe(Effect.orElseSucceed(() => ""));
60
+ return yield* Effect.fail(httpStatusError(response.status, text));
61
+ }
62
+ const json = yield* response.json.pipe(Effect.mapError(transportFailure));
63
+ const wire = yield* decodeWire(json).pipe(Effect.mapError((cause) => new AiError.GenerationFailed({
64
+ provider: "elevenlabs",
65
+ raw: cause
66
+ })));
67
+ const words = wire.words?.map(toWordTimestamp).filter((w) => w !== void 0);
68
+ return {
69
+ text: wire.text,
70
+ ...wire.language_code !== void 0 && { languageCode: wire.language_code },
71
+ ...words !== void 0 && words.length > 0 && { words },
72
+ raw: json
73
+ };
74
+ });
75
+ const make = (cfg) => Effect.gen(function* () {
76
+ const client = yield* HttpClient.HttpClient;
77
+ const ctor = yield* Socket.WebSocketConstructor;
78
+ return {
79
+ transcribe: (r) => transcribeImpl(cfg)(r).pipe(Effect.provideService(HttpClient.HttpClient, client)),
80
+ streamTranscriptionFrom: (audioIn, request) => streamTranscription(cfg)(audioIn, request).pipe(Stream.provideService(HttpClient.HttpClient, client), Stream.provideService(Socket.WebSocketConstructor, ctor))
81
+ };
82
+ });
83
+ /**
84
+ * Layer registers `ElevenLabsTranscriber`, the generic `Transcriber`,
85
+ * **and the `SttStreaming` capability marker** — `streamTranscriptionFrom`
86
+ * is wired to the realtime WebSocket. Provide
87
+ * `Socket.layerWebSocketConstructorGlobal` (or a custom constructor) +
88
+ * an `HttpClient` Layer at the call site.
89
+ */
90
+ const layer = (cfg) => Layer.mergeAll(Layer.effect(ElevenLabsTranscriber, make(cfg)), Layer.effect(Transcriber, Effect.map(make(cfg), (s) => ({
91
+ transcribe: (req) => s.transcribe(req),
92
+ streamTranscriptionFrom: s.streamTranscriptionFrom
93
+ }))), Layer.succeed(SttStreaming, void 0));
94
+ //#endregion
95
+ export { ElevenLabsTranscriber, layer, make, ElevenLabsTranscriber_exports as t };
96
+
97
+ //# sourceMappingURL=ElevenLabsTranscriber.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ElevenLabsTranscriber.mjs","names":[],"sources":["../src/ElevenLabsTranscriber.ts"],"sourcesContent":["import { Context, Effect, Layer, Redacted, Schema, Stream } from \"effect\"\nimport { HttpClient, HttpClientRequest } from \"effect/unstable/http\"\nimport * as Socket from \"effect/unstable/socket/Socket\"\nimport * as AiError from \"@effect-uai/core/AiError\"\nimport type { TranscriptResult, WordTimestamp } from \"@effect-uai/core/Transcript\"\nimport {\n type CommonTranscribeRequest,\n SttStreaming,\n Transcriber,\n type TranscriberService,\n} from \"@effect-uai/core/Transcriber\"\nimport { audioToBlob, defaultFileName, httpStatusError, transportFailure } from \"./codec.js\"\nimport type { ElevenLabsSttModel } from \"./models.js\"\nimport { streamTranscription } from \"./realtimeStt.js\"\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\n/**\n * ElevenLabs-typed transcribe request. `model` narrows to\n * `ElevenLabsSttModel`. `numSpeakers` hints diarization. `audioEvents`\n * surfaces `(laughter)` / `(music)` tags inline in `text` (provider\n * default: true). `fileName` overrides the multipart upload's\n * `filename`; ElevenLabs uses the extension to detect format.\n */\nexport type ElevenLabsTranscribeRequest = Omit<CommonTranscribeRequest, \"model\"> & {\n readonly model: ElevenLabsSttModel\n readonly numSpeakers?: number\n readonly audioEvents?: boolean\n readonly fileName?: string\n}\n\nexport type ElevenLabsTranscriberService = {\n readonly transcribe: (\n r: ElevenLabsTranscribeRequest,\n ) => Effect.Effect<TranscriptResult, AiError.AiError>\n readonly streamTranscriptionFrom: TranscriberService[\"streamTranscriptionFrom\"]\n}\n\nexport class ElevenLabsTranscriber extends Context.Service<\n ElevenLabsTranscriber,\n ElevenLabsTranscriberService\n>()(\"@betalyra/effect-uai/providers/elevenlabs/ElevenLabsTranscriber\") {}\n\nexport type Config = { readonly apiKey: Redacted.Redacted; readonly baseUrl?: string }\n\n// ---------------------------------------------------------------------------\n// Response schema\n// ---------------------------------------------------------------------------\n\nconst Word = Schema.Struct({\n text: Schema.String,\n start: Schema.optional(Schema.Number),\n end: Schema.optional(Schema.Number),\n type: Schema.optional(Schema.String),\n speaker_id: Schema.optional(Schema.String),\n logprob: Schema.optional(Schema.Number),\n})\n\nconst Wire = Schema.Struct({\n text: Schema.String,\n language_code: Schema.optional(Schema.String),\n language_probability: Schema.optional(Schema.Number),\n words: Schema.optional(Schema.Array(Word)),\n transcription_id: Schema.optional(Schema.String),\n})\nconst decodeWire = Schema.decodeUnknownEffect(Wire)\n\nconst toWordTimestamp = (w: typeof Word.Type): WordTimestamp | undefined =>\n w.start === undefined || w.end === undefined\n ? undefined\n : {\n text: w.text,\n startSeconds: w.start,\n endSeconds: w.end,\n ...(w.logprob !== undefined && { confidence: Math.exp(w.logprob) }),\n ...(w.speaker_id !== undefined && { speakerId: w.speaker_id }),\n }\n\n// ---------------------------------------------------------------------------\n// Multipart body\n// ---------------------------------------------------------------------------\n\nconst buildForm = (request: ElevenLabsTranscribeRequest) =>\n Effect.gen(function* () {\n const blob = yield* audioToBlob(request.audio)\n const fileName = request.fileName ?? defaultFileName(request.audio.mimeType ?? \"\")\n const form = new FormData()\n form.set(\"model_id\", request.model)\n form.set(\"file\", blob, fileName)\n if (request.language !== undefined) form.set(\"language_code\", request.language)\n if (request.diarization !== undefined)\n form.set(\"diarize\", request.diarization ? \"true\" : \"false\")\n if (request.wordTimestamps === true) form.set(\"timestamps_granularity\", \"word\")\n if (request.numSpeakers !== undefined) form.set(\"num_speakers\", String(request.numSpeakers))\n if (request.audioEvents !== undefined)\n form.set(\"tag_audio_events\", request.audioEvents ? \"true\" : \"false\")\n return form\n })\n\n// ---------------------------------------------------------------------------\n// HTTP plumbing\n// ---------------------------------------------------------------------------\n\nconst baseUrl = (cfg: Config) => cfg.baseUrl ?? \"https://api.elevenlabs.io/v1\"\n\nconst transcribeImpl = (cfg: Config) => (request: ElevenLabsTranscribeRequest) =>\n Effect.gen(function* () {\n const client = yield* HttpClient.HttpClient\n const form = yield* buildForm(request)\n const httpRequest = HttpClientRequest.post(`${baseUrl(cfg)}/speech-to-text`).pipe(\n HttpClientRequest.setHeader(\"xi-api-key\", Redacted.value(cfg.apiKey)),\n HttpClientRequest.bodyFormData(form),\n )\n const response = yield* client.execute(httpRequest).pipe(Effect.mapError(transportFailure))\n if (response.status >= 400) {\n const text = yield* response.text.pipe(Effect.orElseSucceed(() => \"\"))\n return yield* Effect.fail(httpStatusError(response.status, text))\n }\n const json = yield* response.json.pipe(Effect.mapError(transportFailure))\n const wire = yield* decodeWire(json).pipe(\n Effect.mapError(\n (cause) => new AiError.GenerationFailed({ provider: \"elevenlabs\", raw: cause }),\n ),\n )\n const words = wire.words\n ?.map(toWordTimestamp)\n .filter((w): w is WordTimestamp => w !== undefined)\n return {\n text: wire.text,\n ...(wire.language_code !== undefined && { languageCode: wire.language_code }),\n ...(words !== undefined && words.length > 0 && { words }),\n raw: json,\n } satisfies TranscriptResult\n })\n\n// ---------------------------------------------------------------------------\n// Constructors\n// ---------------------------------------------------------------------------\n\nexport const make = (cfg: Config) =>\n Effect.gen(function* () {\n const client = yield* HttpClient.HttpClient\n const ctor = yield* Socket.WebSocketConstructor\n return {\n transcribe: (r) =>\n transcribeImpl(cfg)(r).pipe(Effect.provideService(HttpClient.HttpClient, client)),\n streamTranscriptionFrom: (audioIn, request) =>\n streamTranscription(cfg)(audioIn, request).pipe(\n Stream.provideService(HttpClient.HttpClient, client),\n Stream.provideService(Socket.WebSocketConstructor, ctor),\n ),\n } satisfies ElevenLabsTranscriberService\n })\n\n/**\n * Layer registers `ElevenLabsTranscriber`, the generic `Transcriber`,\n * **and the `SttStreaming` capability marker** — `streamTranscriptionFrom`\n * is wired to the realtime WebSocket. Provide\n * `Socket.layerWebSocketConstructorGlobal` (or a custom constructor) +\n * an `HttpClient` Layer at the call site.\n */\nexport const layer = (cfg: Config) =>\n Layer.mergeAll(\n Layer.effect(ElevenLabsTranscriber, make(cfg)),\n Layer.effect(\n Transcriber,\n Effect.map(\n make(cfg),\n (s): TranscriberService => ({\n transcribe: (req: CommonTranscribeRequest) =>\n s.transcribe(req as ElevenLabsTranscribeRequest),\n streamTranscriptionFrom: s.streamTranscriptionFrom,\n }),\n ),\n ),\n Layer.succeed(SttStreaming, undefined),\n )\n"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export { };
@@ -0,0 +1,58 @@
1
+ import { i as it, n as globalExpect, r as describe, t as import_dist } from "./dist-DMsg8YLb.mjs";
2
+ import { ElevenLabsTranscriber, layer } from "./ElevenLabsTranscriber.mjs";
3
+ import { Effect, Layer, Redacted, Stream } from "effect";
4
+ import { FetchHttpClient } from "effect/unstable/http";
5
+ import * as Socket from "effect/unstable/socket/Socket";
6
+ import * as Transcriber$1 from "@effect-uai/core/Transcriber";
7
+ const live = layer({ apiKey: Redacted.make("test-key") }).pipe(Layer.provide(FetchHttpClient.layer), Layer.provide(Socket.layerWebSocketConstructorGlobal));
8
+ const dummyAudio = {
9
+ _tag: "bytes",
10
+ bytes: new Uint8Array([
11
+ 0,
12
+ 1,
13
+ 2,
14
+ 3
15
+ ]),
16
+ mimeType: "audio/wav"
17
+ };
18
+ describe("ElevenLabsTranscriber input format guard (runtime)", () => {
19
+ it("fails Unsupported for unsupported raw encodings", async () => {
20
+ const program = ElevenLabsTranscriber.use((s) => Stream.runDrain(s.streamTranscriptionFrom(Stream.fromIterable([new Uint8Array([0])]), {
21
+ model: "scribe_v2_realtime",
22
+ inputFormat: {
23
+ container: "mp3",
24
+ encoding: "mp3",
25
+ sampleRate: 44100
26
+ }
27
+ })));
28
+ const exit = await Effect.runPromiseExit(program.pipe(Effect.provide(live)));
29
+ globalExpect(exit._tag).toBe("Failure");
30
+ if (exit._tag === "Failure") {
31
+ globalExpect(JSON.stringify(exit.cause)).toContain("Unsupported");
32
+ globalExpect(JSON.stringify(exit.cause)).toContain("inputFormat");
33
+ }
34
+ });
35
+ });
36
+ describe("ElevenLabsTranscriber Layer (compile-time)", () => {
37
+ it("registers `SttStreaming` — `streamTranscriptionFrom` clears R to never", () => {
38
+ const events = Stream.fromIterable([new Uint8Array([0])]).pipe(Transcriber$1.streamTranscriptionFrom({
39
+ model: "scribe_v2_realtime",
40
+ inputFormat: {
41
+ container: "raw",
42
+ encoding: "pcm_s16le",
43
+ sampleRate: 16e3
44
+ }
45
+ }));
46
+ (0, import_dist.expectTypeOf)(Stream.runDrain(events).pipe(Effect.provide(live))).toEqualTypeOf();
47
+ });
48
+ it("sync `transcribe` requires no marker", () => {
49
+ (0, import_dist.expectTypeOf)(Transcriber$1.transcribe({
50
+ audio: dummyAudio,
51
+ model: "scribe_v2"
52
+ }).pipe(Effect.provide(live))).toEqualTypeOf();
53
+ });
54
+ });
55
+ //#endregion
56
+ export {};
57
+
58
+ //# sourceMappingURL=ElevenLabsTranscriber.test.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ElevenLabsTranscriber.test.mjs","names":["ElevenLabsTranscriber.layer","Transcriber"],"sources":["../src/ElevenLabsTranscriber.test.ts"],"sourcesContent":["import { Effect, Layer, Redacted, Stream } from \"effect\"\nimport { FetchHttpClient } from \"effect/unstable/http\"\nimport * as Socket from \"effect/unstable/socket/Socket\"\nimport { describe, expect, expectTypeOf, it } from \"vitest\"\nimport type * as AiError from \"@effect-uai/core/AiError\"\nimport type { TranscriptResult } from \"@effect-uai/core/Transcript\"\nimport * as Transcriber from \"@effect-uai/core/Transcriber\"\nimport * as ElevenLabsTranscriber from \"./ElevenLabsTranscriber.js\"\n\nconst cfg: ElevenLabsTranscriber.Config = { apiKey: Redacted.make(\"test-key\") }\n// FetchHttpClient + globalThis.WebSocket are required for `make`, but these\n// tests only exercise the codec + compile-time / runtime branches — no real\n// HTTP or WS connection is opened.\nconst live = ElevenLabsTranscriber.layer(cfg).pipe(\n Layer.provide(FetchHttpClient.layer),\n Layer.provide(Socket.layerWebSocketConstructorGlobal),\n)\n\nconst dummyAudio = {\n _tag: \"bytes\" as const,\n bytes: new Uint8Array([0, 1, 2, 3]),\n mimeType: \"audio/wav\" as const,\n}\n\ndescribe(\"ElevenLabsTranscriber input format guard (runtime)\", () => {\n it(\"fails Unsupported for unsupported raw encodings\", async () => {\n const program = ElevenLabsTranscriber.ElevenLabsTranscriber.use((s) =>\n Stream.runDrain(\n s.streamTranscriptionFrom(Stream.fromIterable([new Uint8Array([0])]), {\n model: \"scribe_v2_realtime\",\n inputFormat: { container: \"mp3\", encoding: \"mp3\", sampleRate: 44100 },\n }),\n ),\n )\n const exit = await Effect.runPromiseExit(program.pipe(Effect.provide(live)))\n expect(exit._tag).toBe(\"Failure\")\n if (exit._tag === \"Failure\") {\n expect(JSON.stringify(exit.cause)).toContain(\"Unsupported\")\n expect(JSON.stringify(exit.cause)).toContain(\"inputFormat\")\n }\n })\n})\n\ndescribe(\"ElevenLabsTranscriber Layer (compile-time)\", () => {\n it(\"registers `SttStreaming` — `streamTranscriptionFrom` clears R to never\", () => {\n const audio: Stream.Stream<Uint8Array> = Stream.fromIterable([new Uint8Array([0])])\n const events = audio.pipe(\n Transcriber.streamTranscriptionFrom({\n model: \"scribe_v2_realtime\",\n inputFormat: { container: \"raw\", encoding: \"pcm_s16le\", sampleRate: 16000 },\n }),\n )\n const provided = Stream.runDrain(events).pipe(Effect.provide(live))\n expectTypeOf(provided).toEqualTypeOf<Effect.Effect<void, AiError.AiError, never>>()\n })\n\n it(\"sync `transcribe` requires no marker\", () => {\n const t = Transcriber.transcribe({ audio: dummyAudio, model: \"scribe_v2\" }).pipe(\n Effect.provide(live),\n )\n expectTypeOf(t).toEqualTypeOf<Effect.Effect<TranscriptResult, AiError.AiError, never>>()\n })\n})\n"],"mappings":";;;;;;AAaA,MAAM,OAAOA,MAA4B,EAJG,QAAQ,SAAS,KAAK,WAAW,EAIpC,CAAI,CAAC,KAC5C,MAAM,QAAQ,gBAAgB,MAAM,EACpC,MAAM,QAAQ,OAAO,gCAAgC,CACtD;AAED,MAAM,aAAa;CACjB,MAAM;CACN,OAAO,IAAI,WAAW;EAAC;EAAG;EAAG;EAAG;EAAE,CAAC;CACnC,UAAU;CACX;AAED,SAAS,4DAA4D;AACnE,IAAG,mDAAmD,YAAY;EAChE,MAAM,UAAA,sBAAsD,KAAK,MAC/D,OAAO,SACL,EAAE,wBAAwB,OAAO,aAAa,CAAC,IAAI,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE;GACpE,OAAO;GACP,aAAa;IAAE,WAAW;IAAO,UAAU;IAAO,YAAY;IAAO;GACtE,CAAC,CACH,CACF;EACD,MAAM,OAAO,MAAM,OAAO,eAAe,QAAQ,KAAK,OAAO,QAAQ,KAAK,CAAC,CAAC;AAC5E,eAAO,KAAK,KAAK,CAAC,KAAK,UAAU;AACjC,MAAI,KAAK,SAAS,WAAW;AAC3B,gBAAO,KAAK,UAAU,KAAK,MAAM,CAAC,CAAC,UAAU,cAAc;AAC3D,gBAAO,KAAK,UAAU,KAAK,MAAM,CAAC,CAAC,UAAU,cAAc;;GAE7D;EACF;AAEF,SAAS,oDAAoD;AAC3D,IAAG,gFAAgF;EAEjF,MAAM,SADmC,OAAO,aAAa,CAAC,IAAI,WAAW,CAAC,EAAE,CAAC,CAAC,CAC9D,CAAC,KACnBC,cAAY,wBAAwB;GAClC,OAAO;GACP,aAAa;IAAE,WAAW;IAAO,UAAU;IAAa,YAAY;IAAO;GAC5E,CAAC,CACH;AAED,GAAA,GAAA,YAAA,cADiB,OAAO,SAAS,OAAO,CAAC,KAAK,OAAO,QAAQ,KAAK,CAC7C,CAAC,CAAC,eAA4D;GACnF;AAEF,IAAG,8CAA8C;AAI/C,GAAA,GAAA,YAAA,cAHUA,cAAY,WAAW;GAAE,OAAO;GAAY,OAAO;GAAa,CAAC,CAAC,KAC1E,OAAO,QAAQ,KAAK,CAER,CAAC,CAAC,eAAwE;GACxF;EACF"}
@@ -0,0 +1,14 @@
1
+ //#region \0rolldown/runtime.js
2
+ var __defProp = Object.defineProperty;
3
+ var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
4
+ var __exportAll = (all, no_symbols) => {
5
+ let target = {};
6
+ for (var name in all) __defProp(target, name, {
7
+ get: all[name],
8
+ enumerable: true
9
+ });
10
+ if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
11
+ return target;
12
+ };
13
+ //#endregion
14
+ export { __exportAll as n, __commonJSMin as t };
@@ -0,0 +1,43 @@
1
+ import { Effect } from "effect";
2
+ import * as AiError from "@effect-uai/core/AiError";
3
+ import { AudioFormat, AudioSource } from "@effect-uai/core/Audio";
4
+
5
+ //#region src/codec.d.ts
6
+ declare namespace codec_d_exports {
7
+ export { VoiceSettings, audioToBlob, defaultFileName, defaultFormat, formatToOutputSlug, httpStatusError, transportFailure, wireVoiceSettings };
8
+ }
9
+ type VoiceSettings = {
10
+ readonly stability?: number;
11
+ readonly similarityBoost?: number;
12
+ readonly style?: number;
13
+ readonly useSpeakerBoost?: boolean;
14
+ readonly speed?: number;
15
+ };
16
+ declare const wireVoiceSettings: (v: VoiceSettings | undefined) => {
17
+ speed?: number;
18
+ use_speaker_boost?: boolean;
19
+ style?: number;
20
+ similarity_boost?: number;
21
+ stability?: number;
22
+ } | undefined;
23
+ /**
24
+ * ElevenLabs encodes container + sample rate + bitrate in a single
25
+ * dot-less slug (`mp3_44100_128`, `pcm_16000`, `wav_48000`, `ulaw_8000`,
26
+ * `opus_48000_128`, etc.). This helper inverts the common cases of our
27
+ * `AudioFormat` shape into that slug.
28
+ *
29
+ * Only the formats that map cleanly are produced. Anything we can't
30
+ * encode (mismatched bitrate, unsupported sample rate combination)
31
+ * fails `Unsupported` with the requested format echoed so the user can
32
+ * fix it.
33
+ */
34
+ declare const formatToOutputSlug: (format: AudioFormat) => Effect.Effect<string, AiError.AiError>;
35
+ /** Default output: 128 kbps MP3 at 44.1 kHz. */
36
+ declare const defaultFormat: AudioFormat;
37
+ declare const audioToBlob: (audio: AudioSource) => Effect.Effect<Blob, AiError.AiError>;
38
+ declare const defaultFileName: (mimeType: string) => string;
39
+ declare const httpStatusError: (status: number, body: string) => AiError.AiError;
40
+ declare const transportFailure: (cause: unknown) => AiError.AiError;
41
+ //#endregion
42
+ export { VoiceSettings, audioToBlob, defaultFileName, defaultFormat, formatToOutputSlug, httpStatusError, codec_d_exports as t, transportFailure, wireVoiceSettings };
43
+ //# sourceMappingURL=codec.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codec.d.mts","names":[],"sources":["../src/codec.ts"],"mappings":";;;;;;;;KAQY,aAAA;EAAA,SACD,SAAA;EAAA,SACA,eAAA;EAAA,SACA,KAAA;EAAA,SACA,eAAA;EAAA,SACA,KAAA;AAAA;AAAA,cAGE,iBAAA,GAAqB,CAAA,EAAG,aAAA;;;;;;;;;;;;;;;;;AAArC;cA0Ba,kBAAA,GAAqB,MAAA,EAAQ,WAAA,KAAgB,MAAA,CAAO,MAAA,SAAe,OAAA,CAAQ,OAAA;;cAgC3E,aAAA,EAAe,WAAA;AAAA,cA6Bf,WAAA,GAAc,KAAA,EAAO,WAAA,KAAgB,MAAA,CAAO,MAAA,CAAO,IAAA,EAAM,OAAA,CAAQ,OAAA;AAAA,cA2BjE,eAAA,GAAmB,QAAA;AAAA,cAYnB,eAAA,GAAkB,MAAA,UAAgB,IAAA,aAAiB,OAAA,CAAQ,OAAA;AAAA,cAyC3D,gBAAA,GAAoB,KAAA,cAAiB,OAAA,CAAQ,OAAA"}