@effect-uai/core 0.3.0 → 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 (97) hide show
  1. package/dist/{AiError-CBuPHVKA.d.mts → AiError-csR8Bhxx.d.mts} +26 -4
  2. package/dist/{AiError-CBuPHVKA.d.mts.map → AiError-csR8Bhxx.d.mts.map} +1 -1
  3. package/dist/Audio-BfCTGnH3.d.mts +61 -0
  4. package/dist/Audio-BfCTGnH3.d.mts.map +1 -0
  5. package/dist/{Image-BZmKfIdq.d.mts → Image-DxyXqzAM.d.mts} +4 -4
  6. package/dist/{Image-BZmKfIdq.d.mts.map → Image-DxyXqzAM.d.mts.map} +1 -1
  7. package/dist/{Items-CB8Bo3FI.d.mts → Items-Hg5AsYxl.d.mts} +5 -5
  8. package/dist/{Items-CB8Bo3FI.d.mts.map → Items-Hg5AsYxl.d.mts.map} +1 -1
  9. package/dist/{StructuredFormat-BWq5Hd1O.d.mts → StructuredFormat-Cl41C56K.d.mts} +1 -1
  10. package/dist/{StructuredFormat-BWq5Hd1O.d.mts.map → StructuredFormat-Cl41C56K.d.mts.map} +1 -1
  11. package/dist/{Tool-DjVufH7i.d.mts → Tool-B8B5qVEy.d.mts} +2 -2
  12. package/dist/{Tool-DjVufH7i.d.mts.map → Tool-B8B5qVEy.d.mts.map} +1 -1
  13. package/dist/{Turn-OPaILVIB.d.mts → Turn-7geUcKsf.d.mts} +4 -4
  14. package/dist/{Turn-OPaILVIB.d.mts.map → Turn-7geUcKsf.d.mts.map} +1 -1
  15. package/dist/domain/AiError.d.mts +2 -2
  16. package/dist/domain/AiError.mjs +18 -2
  17. package/dist/domain/AiError.mjs.map +1 -1
  18. package/dist/domain/Audio.d.mts +2 -0
  19. package/dist/domain/Audio.mjs +14 -0
  20. package/dist/domain/Audio.mjs.map +1 -0
  21. package/dist/domain/Image.d.mts +1 -1
  22. package/dist/domain/Items.d.mts +1 -1
  23. package/dist/domain/Music.d.mts +116 -0
  24. package/dist/domain/Music.d.mts.map +1 -0
  25. package/dist/domain/Music.mjs +29 -0
  26. package/dist/domain/Music.mjs.map +1 -0
  27. package/dist/domain/Transcript.d.mts +95 -0
  28. package/dist/domain/Transcript.d.mts.map +1 -0
  29. package/dist/domain/Transcript.mjs +22 -0
  30. package/dist/domain/Transcript.mjs.map +1 -0
  31. package/dist/domain/Turn.d.mts +1 -1
  32. package/dist/embedding-model/Embedding.d.mts +1 -1
  33. package/dist/embedding-model/EmbeddingModel.d.mts +1 -1
  34. package/dist/index.d.mts +13 -7
  35. package/dist/index.mjs +7 -1
  36. package/dist/language-model/LanguageModel.d.mts +5 -5
  37. package/dist/loop/Loop.d.mts +2 -2
  38. package/dist/music-generator/MusicGenerator.d.mts +77 -0
  39. package/dist/music-generator/MusicGenerator.d.mts.map +1 -0
  40. package/dist/music-generator/MusicGenerator.mjs +51 -0
  41. package/dist/music-generator/MusicGenerator.mjs.map +1 -0
  42. package/dist/music-generator/MusicGenerator.test.d.mts +1 -0
  43. package/dist/music-generator/MusicGenerator.test.mjs +154 -0
  44. package/dist/music-generator/MusicGenerator.test.mjs.map +1 -0
  45. package/dist/speech-synthesizer/SpeechSynthesizer.d.mts +96 -0
  46. package/dist/speech-synthesizer/SpeechSynthesizer.d.mts.map +1 -0
  47. package/dist/speech-synthesizer/SpeechSynthesizer.mjs +48 -0
  48. package/dist/speech-synthesizer/SpeechSynthesizer.mjs.map +1 -0
  49. package/dist/speech-synthesizer/SpeechSynthesizer.test.d.mts +1 -0
  50. package/dist/speech-synthesizer/SpeechSynthesizer.test.mjs +112 -0
  51. package/dist/speech-synthesizer/SpeechSynthesizer.test.mjs.map +1 -0
  52. package/dist/streaming/JSONL.d.mts +10 -3
  53. package/dist/streaming/JSONL.d.mts.map +1 -1
  54. package/dist/streaming/JSONL.mjs +12 -1
  55. package/dist/streaming/JSONL.mjs.map +1 -1
  56. package/dist/structured-format/StructuredFormat.d.mts +1 -1
  57. package/dist/testing/MockMusicGenerator.d.mts +39 -0
  58. package/dist/testing/MockMusicGenerator.d.mts.map +1 -0
  59. package/dist/testing/MockMusicGenerator.mjs +96 -0
  60. package/dist/testing/MockMusicGenerator.mjs.map +1 -0
  61. package/dist/testing/MockProvider.d.mts +2 -2
  62. package/dist/testing/MockSpeechSynthesizer.d.mts +37 -0
  63. package/dist/testing/MockSpeechSynthesizer.d.mts.map +1 -0
  64. package/dist/testing/MockSpeechSynthesizer.mjs +95 -0
  65. package/dist/testing/MockSpeechSynthesizer.mjs.map +1 -0
  66. package/dist/testing/MockTranscriber.d.mts +37 -0
  67. package/dist/testing/MockTranscriber.d.mts.map +1 -0
  68. package/dist/testing/MockTranscriber.mjs +77 -0
  69. package/dist/testing/MockTranscriber.mjs.map +1 -0
  70. package/dist/tool/HistoryCheck.d.mts +1 -1
  71. package/dist/tool/Outcome.d.mts +1 -1
  72. package/dist/tool/Resolvers.d.mts +1 -1
  73. package/dist/tool/Tool.d.mts +1 -1
  74. package/dist/tool/Toolkit.d.mts +2 -2
  75. package/dist/transcriber/Transcriber.d.mts +101 -0
  76. package/dist/transcriber/Transcriber.d.mts.map +1 -0
  77. package/dist/transcriber/Transcriber.mjs +49 -0
  78. package/dist/transcriber/Transcriber.mjs.map +1 -0
  79. package/dist/transcriber/Transcriber.test.d.mts +1 -0
  80. package/dist/transcriber/Transcriber.test.mjs +130 -0
  81. package/dist/transcriber/Transcriber.test.mjs.map +1 -0
  82. package/package.json +37 -1
  83. package/src/domain/AiError.ts +21 -0
  84. package/src/domain/Audio.ts +88 -0
  85. package/src/domain/Music.ts +121 -0
  86. package/src/domain/Transcript.ts +83 -0
  87. package/src/index.ts +6 -0
  88. package/src/music-generator/MusicGenerator.test.ts +170 -0
  89. package/src/music-generator/MusicGenerator.ts +123 -0
  90. package/src/speech-synthesizer/SpeechSynthesizer.test.ts +141 -0
  91. package/src/speech-synthesizer/SpeechSynthesizer.ts +131 -0
  92. package/src/streaming/JSONL.ts +12 -0
  93. package/src/testing/MockMusicGenerator.ts +170 -0
  94. package/src/testing/MockSpeechSynthesizer.ts +165 -0
  95. package/src/testing/MockTranscriber.ts +139 -0
  96. package/src/transcriber/Transcriber.test.ts +125 -0
  97. package/src/transcriber/Transcriber.ts +127 -0
@@ -0,0 +1,95 @@
1
+ import { InvalidRequest } from "../domain/AiError.mjs";
2
+ import { SpeechSynthesizer, TtsIncrementalText } from "../speech-synthesizer/SpeechSynthesizer.mjs";
3
+ import { Effect, Layer, Ref, Stream } from "effect";
4
+ //#region src/testing/MockSpeechSynthesizer.ts
5
+ const makeService = (script, record) => Effect.gen(function* () {
6
+ const bCursor = yield* Ref.make(0);
7
+ const ssCursor = yield* Ref.make(0);
8
+ const ssfCursor = yield* Ref.make(0);
9
+ return {
10
+ synthesize: (request) => Effect.gen(function* () {
11
+ yield* record.synthesize(request);
12
+ const i = yield* Ref.getAndUpdate(bCursor, (n) => n + 1);
13
+ const scripted = script.blobs ?? [];
14
+ if (i >= scripted.length) return yield* Effect.fail(new InvalidRequest({
15
+ provider: "mock",
16
+ raw: `MockSpeechSynthesizer exhausted: ${scripted.length} blobs scripted, but call ${i + 1} was made`
17
+ }));
18
+ return scripted[i];
19
+ }),
20
+ streamSynthesis: (request) => Stream.unwrap(Effect.gen(function* () {
21
+ yield* record.streamSynthesis(request);
22
+ const i = yield* Ref.getAndUpdate(ssCursor, (n) => n + 1);
23
+ const scripted = script.streamSynthesisChunks ?? [];
24
+ if (i >= scripted.length) return Stream.fail(new InvalidRequest({
25
+ provider: "mock",
26
+ raw: `MockSpeechSynthesizer exhausted: ${scripted.length} streamSynthesis lists scripted, but call ${i + 1} was made`
27
+ }));
28
+ return Stream.fromIterable(scripted[i]);
29
+ })),
30
+ streamSynthesisFrom: (textIn, request) => Stream.unwrap(Effect.gen(function* () {
31
+ yield* record.streamSynthesisFrom(request);
32
+ const i = yield* Ref.getAndUpdate(ssfCursor, (n) => n + 1);
33
+ const scripted = script.streamSynthesisFromChunks ?? [];
34
+ if (i >= scripted.length) return Stream.fail(new InvalidRequest({
35
+ provider: "mock",
36
+ raw: `MockSpeechSynthesizer exhausted: ${scripted.length} streamSynthesisFrom lists scripted, but call ${i + 1} was made`
37
+ }));
38
+ return Stream.drain(textIn).pipe(Stream.concat(Stream.fromIterable(scripted[i])));
39
+ }))
40
+ };
41
+ });
42
+ /**
43
+ * Layer providing the `SpeechSynthesizer` service AND the
44
+ * `TtsIncrementalText` capability marker. Use for the common case
45
+ * where code under test exercises `streamSynthesisFrom`.
46
+ */
47
+ const layer = (script) => {
48
+ const bCalls = Ref.makeUnsafe([]);
49
+ const ssCalls = Ref.makeUnsafe([]);
50
+ const ssfCalls = Ref.makeUnsafe([]);
51
+ const synthesizerLayer = Layer.effect(SpeechSynthesizer, makeService(script, {
52
+ synthesize: (req) => Ref.update(bCalls, (xs) => [...xs, req]),
53
+ streamSynthesis: (req) => Ref.update(ssCalls, (xs) => [...xs, req]),
54
+ streamSynthesisFrom: (req) => Ref.update(ssfCalls, (xs) => [...xs, req])
55
+ }));
56
+ return {
57
+ layer: Layer.merge(synthesizerLayer, Layer.succeed(TtsIncrementalText, void 0)),
58
+ recorder: Effect.gen(function* () {
59
+ return {
60
+ synthesizeCalls: yield* Ref.get(bCalls),
61
+ streamSynthesisCalls: yield* Ref.get(ssCalls),
62
+ streamSynthesisFromCalls: yield* Ref.get(ssfCalls)
63
+ };
64
+ })
65
+ };
66
+ };
67
+ /**
68
+ * Variant that omits the `TtsIncrementalText` marker — simulates a
69
+ * provider without incremental-text-in support (e.g. OpenAI, AWS
70
+ * Polly non-Generative). Calls to `streamSynthesisFrom` in code under
71
+ * test should be a compile-time error.
72
+ */
73
+ const layerWithoutIncremental = (script) => {
74
+ const bCalls = Ref.makeUnsafe([]);
75
+ const ssCalls = Ref.makeUnsafe([]);
76
+ const ssfCalls = Ref.makeUnsafe([]);
77
+ return {
78
+ layer: Layer.effect(SpeechSynthesizer, makeService(script, {
79
+ synthesize: (req) => Ref.update(bCalls, (xs) => [...xs, req]),
80
+ streamSynthesis: (req) => Ref.update(ssCalls, (xs) => [...xs, req]),
81
+ streamSynthesisFrom: (req) => Ref.update(ssfCalls, (xs) => [...xs, req])
82
+ })),
83
+ recorder: Effect.gen(function* () {
84
+ return {
85
+ synthesizeCalls: yield* Ref.get(bCalls),
86
+ streamSynthesisCalls: yield* Ref.get(ssCalls),
87
+ streamSynthesisFromCalls: yield* Ref.get(ssfCalls)
88
+ };
89
+ })
90
+ };
91
+ };
92
+ //#endregion
93
+ export { layer, layerWithoutIncremental };
94
+
95
+ //# sourceMappingURL=MockSpeechSynthesizer.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MockSpeechSynthesizer.mjs","names":["AiError.InvalidRequest"],"sources":["../../src/testing/MockSpeechSynthesizer.ts"],"sourcesContent":["import { Effect, Layer, Ref, Stream } from \"effect\"\nimport type { AudioBlob, AudioChunk } from \"../domain/Audio.js\"\nimport * as AiError from \"../domain/AiError.js\"\nimport {\n SpeechSynthesizer,\n TtsIncrementalText,\n type CommonStreamSynthesizeRequest,\n type CommonSynthesizeRequest,\n type SpeechSynthesizerService,\n} from \"../speech-synthesizer/SpeechSynthesizer.js\"\n\nexport type MockSynthesizerRecorder = {\n readonly synthesizeCalls: ReadonlyArray<CommonSynthesizeRequest>\n readonly streamSynthesisCalls: ReadonlyArray<CommonSynthesizeRequest>\n readonly streamSynthesisFromCalls: ReadonlyArray<CommonStreamSynthesizeRequest>\n}\n\nexport type MockSynthesizerScript = {\n /** One blob per `synthesize` call, consumed in order. */\n readonly blobs?: ReadonlyArray<AudioBlob>\n /** One chunk-list per `streamSynthesis` call, consumed in order. */\n readonly streamSynthesisChunks?: ReadonlyArray<ReadonlyArray<AudioChunk>>\n /** One chunk-list per `streamSynthesisFrom` call, consumed in order. */\n readonly streamSynthesisFromChunks?: ReadonlyArray<ReadonlyArray<AudioChunk>>\n}\n\nconst makeService = (\n script: MockSynthesizerScript,\n record: {\n readonly synthesize: (req: CommonSynthesizeRequest) => Effect.Effect<void>\n readonly streamSynthesis: (req: CommonSynthesizeRequest) => Effect.Effect<void>\n readonly streamSynthesisFrom: (req: CommonStreamSynthesizeRequest) => Effect.Effect<void>\n },\n) =>\n Effect.gen(function* () {\n const bCursor = yield* Ref.make(0)\n const ssCursor = yield* Ref.make(0)\n const ssfCursor = yield* Ref.make(0)\n const service: SpeechSynthesizerService = {\n synthesize: (request) =>\n Effect.gen(function* () {\n yield* record.synthesize(request)\n const i = yield* Ref.getAndUpdate(bCursor, (n) => n + 1)\n const scripted = script.blobs ?? []\n if (i >= scripted.length) {\n return yield* Effect.fail(\n new AiError.InvalidRequest({\n provider: \"mock\",\n raw: `MockSpeechSynthesizer exhausted: ${scripted.length} blobs scripted, but call ${i + 1} was made`,\n }),\n )\n }\n return scripted[i]!\n }),\n streamSynthesis: (request) =>\n Stream.unwrap(\n Effect.gen(function* () {\n yield* record.streamSynthesis(request)\n const i = yield* Ref.getAndUpdate(ssCursor, (n) => n + 1)\n const scripted = script.streamSynthesisChunks ?? []\n if (i >= scripted.length) {\n return Stream.fail(\n new AiError.InvalidRequest({\n provider: \"mock\",\n raw: `MockSpeechSynthesizer exhausted: ${scripted.length} streamSynthesis lists scripted, but call ${i + 1} was made`,\n }),\n )\n }\n return Stream.fromIterable(scripted[i]!)\n }),\n ),\n streamSynthesisFrom: <E, R>(\n textIn: Stream.Stream<string, E, R>,\n request: CommonStreamSynthesizeRequest,\n ): Stream.Stream<AudioChunk, AiError.AiError | E, R> =>\n Stream.unwrap(\n Effect.gen(function* () {\n yield* record.streamSynthesisFrom(request)\n const i = yield* Ref.getAndUpdate(ssfCursor, (n) => n + 1)\n const scripted = script.streamSynthesisFromChunks ?? []\n if (i >= scripted.length) {\n const exhausted: Stream.Stream<AudioChunk, AiError.AiError | E, R> = Stream.fail(\n new AiError.InvalidRequest({\n provider: \"mock\",\n raw: `MockSpeechSynthesizer exhausted: ${scripted.length} streamSynthesisFrom lists scripted, but call ${i + 1} was made`,\n }),\n )\n return exhausted\n }\n // Drain the input text fully before emitting scripted audio chunks,\n // so consumers can assert on what text was pushed.\n return Stream.drain(textIn).pipe(Stream.concat(Stream.fromIterable(scripted[i]!)))\n }),\n ),\n }\n return service\n })\n\n/**\n * Layer providing the `SpeechSynthesizer` service AND the\n * `TtsIncrementalText` capability marker. Use for the common case\n * where code under test exercises `streamSynthesisFrom`.\n */\nexport const layer = (\n script: MockSynthesizerScript,\n): {\n readonly layer: Layer.Layer<SpeechSynthesizer | TtsIncrementalText>\n readonly recorder: Effect.Effect<MockSynthesizerRecorder>\n} => {\n const bCalls = Ref.makeUnsafe<ReadonlyArray<CommonSynthesizeRequest>>([])\n const ssCalls = Ref.makeUnsafe<ReadonlyArray<CommonSynthesizeRequest>>([])\n const ssfCalls = Ref.makeUnsafe<ReadonlyArray<CommonStreamSynthesizeRequest>>([])\n const synthesizerLayer = Layer.effect(\n SpeechSynthesizer,\n makeService(script, {\n synthesize: (req) => Ref.update(bCalls, (xs) => [...xs, req]),\n streamSynthesis: (req) => Ref.update(ssCalls, (xs) => [...xs, req]),\n streamSynthesisFrom: (req) => Ref.update(ssfCalls, (xs) => [...xs, req]),\n }),\n )\n const live = Layer.merge(synthesizerLayer, Layer.succeed(TtsIncrementalText, undefined))\n return {\n layer: live,\n recorder: Effect.gen(function* () {\n const synthesizeCalls = yield* Ref.get(bCalls)\n const streamSynthesisCalls = yield* Ref.get(ssCalls)\n const streamSynthesisFromCalls = yield* Ref.get(ssfCalls)\n return { synthesizeCalls, streamSynthesisCalls, streamSynthesisFromCalls }\n }),\n }\n}\n\n/**\n * Variant that omits the `TtsIncrementalText` marker — simulates a\n * provider without incremental-text-in support (e.g. OpenAI, AWS\n * Polly non-Generative). Calls to `streamSynthesisFrom` in code under\n * test should be a compile-time error.\n */\nexport const layerWithoutIncremental = (\n script: MockSynthesizerScript,\n): {\n readonly layer: Layer.Layer<SpeechSynthesizer>\n readonly recorder: Effect.Effect<MockSynthesizerRecorder>\n} => {\n const bCalls = Ref.makeUnsafe<ReadonlyArray<CommonSynthesizeRequest>>([])\n const ssCalls = Ref.makeUnsafe<ReadonlyArray<CommonSynthesizeRequest>>([])\n const ssfCalls = Ref.makeUnsafe<ReadonlyArray<CommonStreamSynthesizeRequest>>([])\n const live = Layer.effect(\n SpeechSynthesizer,\n makeService(script, {\n synthesize: (req) => Ref.update(bCalls, (xs) => [...xs, req]),\n streamSynthesis: (req) => Ref.update(ssCalls, (xs) => [...xs, req]),\n streamSynthesisFrom: (req) => Ref.update(ssfCalls, (xs) => [...xs, req]),\n }),\n )\n return {\n layer: live,\n recorder: Effect.gen(function* () {\n const synthesizeCalls = yield* Ref.get(bCalls)\n const streamSynthesisCalls = yield* Ref.get(ssCalls)\n const streamSynthesisFromCalls = yield* Ref.get(ssfCalls)\n return { synthesizeCalls, streamSynthesisCalls, streamSynthesisFromCalls }\n }),\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ import { TranscriptEvent, TranscriptResult } from "../domain/Transcript.mjs";
2
+ import { CommonStreamTranscribeRequest, CommonTranscribeRequest, SttStreaming, Transcriber } from "../transcriber/Transcriber.mjs";
3
+ import { Effect, Layer } from "effect";
4
+
5
+ //#region src/testing/MockTranscriber.d.ts
6
+ /**
7
+ * Recorder of every call made to the mock.
8
+ */
9
+ type MockTranscriberRecorder = {
10
+ readonly transcribeCalls: ReadonlyArray<CommonTranscribeRequest>;
11
+ readonly streamCalls: ReadonlyArray<CommonStreamTranscribeRequest>;
12
+ };
13
+ type MockTranscriberScript = {
14
+ /** One result per `transcribe` call, consumed in order. */readonly transcripts?: ReadonlyArray<TranscriptResult>; /** One event-list per `streamTranscriptionFrom` call, consumed in order. */
15
+ readonly streams?: ReadonlyArray<ReadonlyArray<TranscriptEvent>>;
16
+ };
17
+ /**
18
+ * Returns a Layer that provides both the `Transcriber` service and the
19
+ * `SttStreaming` capability marker. Use when the code under test calls
20
+ * `streamTranscriptionFrom`.
21
+ */
22
+ declare const layer: (script: MockTranscriberScript) => {
23
+ readonly layer: Layer.Layer<Transcriber | SttStreaming>;
24
+ readonly recorder: Effect.Effect<MockTranscriberRecorder>;
25
+ };
26
+ /**
27
+ * Variant that omits the `SttStreaming` marker — use to test that
28
+ * consumers calling `streamTranscriptionFrom` fail to compile against
29
+ * a non-streaming provider.
30
+ */
31
+ declare const layerSyncOnly: (script: MockTranscriberScript) => {
32
+ readonly layer: Layer.Layer<Transcriber>;
33
+ readonly recorder: Effect.Effect<MockTranscriberRecorder>;
34
+ };
35
+ //#endregion
36
+ export { MockTranscriberRecorder, MockTranscriberScript, layer, layerSyncOnly };
37
+ //# sourceMappingURL=MockTranscriber.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MockTranscriber.d.mts","names":[],"sources":["../../src/testing/MockTranscriber.ts"],"mappings":";;;;;;;AAcA;KAAY,uBAAA;EAAA,SACD,eAAA,EAAiB,aAAA,CAAc,uBAAA;EAAA,SAC/B,WAAA,EAAa,aAAA,CAAc,6BAAA;AAAA;AAAA,KAG1B,qBAAA;EAHY,oEAKb,WAAA,GAAc,aAAA,CAAc,gBAAA,GALF;EAAA,SAO1B,OAAA,GAAU,aAAA,CAAc,aAAA,CAAc,eAAA;AAAA;;;;;;cA6DpC,KAAA,GACX,MAAA,EAAQ,qBAAA;EAAA,SAEC,KAAA,EAAO,KAAA,CAAM,KAAA,CAAM,WAAA,GAAc,YAAA;EAAA,SACjC,QAAA,EAAU,MAAA,CAAO,MAAA,CAAO,uBAAA;AAAA;;;;;;cA2BtB,aAAA,GACX,MAAA,EAAQ,qBAAA;EAAA,SAEC,KAAA,EAAO,KAAA,CAAM,KAAA,CAAM,WAAA;EAAA,SACnB,QAAA,EAAU,MAAA,CAAO,MAAA,CAAO,uBAAA;AAAA"}
@@ -0,0 +1,77 @@
1
+ import { InvalidRequest } from "../domain/AiError.mjs";
2
+ import { SttStreaming, Transcriber } from "../transcriber/Transcriber.mjs";
3
+ import { Effect, Layer, Ref, Stream } from "effect";
4
+ //#region src/testing/MockTranscriber.ts
5
+ const makeService = (script, record) => Effect.gen(function* () {
6
+ const tCursor = yield* Ref.make(0);
7
+ const sCursor = yield* Ref.make(0);
8
+ return {
9
+ transcribe: (request) => Effect.gen(function* () {
10
+ yield* record.transcribe(request);
11
+ const i = yield* Ref.getAndUpdate(tCursor, (n) => n + 1);
12
+ const scripted = script.transcripts ?? [];
13
+ if (i >= scripted.length) return yield* Effect.fail(new InvalidRequest({
14
+ provider: "mock",
15
+ raw: `MockTranscriber exhausted: ${scripted.length} transcripts scripted, but call ${i + 1} was made`
16
+ }));
17
+ return scripted[i];
18
+ }),
19
+ streamTranscriptionFrom: (audioIn, request) => Stream.unwrap(Effect.gen(function* () {
20
+ yield* record.stream(request);
21
+ const i = yield* Ref.getAndUpdate(sCursor, (n) => n + 1);
22
+ const scripted = script.streams ?? [];
23
+ if (i >= scripted.length) return Stream.fail(new InvalidRequest({
24
+ provider: "mock",
25
+ raw: `MockTranscriber exhausted: ${scripted.length} streams scripted, but call ${i + 1} was made`
26
+ }));
27
+ return Stream.drain(audioIn).pipe(Stream.concat(Stream.fromIterable(scripted[i])));
28
+ }))
29
+ };
30
+ });
31
+ /**
32
+ * Returns a Layer that provides both the `Transcriber` service and the
33
+ * `SttStreaming` capability marker. Use when the code under test calls
34
+ * `streamTranscriptionFrom`.
35
+ */
36
+ const layer = (script) => {
37
+ const tCalls = Ref.makeUnsafe([]);
38
+ const sCalls = Ref.makeUnsafe([]);
39
+ const transcriberLayer = Layer.effect(Transcriber, makeService(script, {
40
+ transcribe: (req) => Ref.update(tCalls, (xs) => [...xs, req]),
41
+ stream: (req) => Ref.update(sCalls, (xs) => [...xs, req])
42
+ }));
43
+ return {
44
+ layer: Layer.merge(transcriberLayer, Layer.succeed(SttStreaming, void 0)),
45
+ recorder: Effect.gen(function* () {
46
+ return {
47
+ transcribeCalls: yield* Ref.get(tCalls),
48
+ streamCalls: yield* Ref.get(sCalls)
49
+ };
50
+ })
51
+ };
52
+ };
53
+ /**
54
+ * Variant that omits the `SttStreaming` marker — use to test that
55
+ * consumers calling `streamTranscriptionFrom` fail to compile against
56
+ * a non-streaming provider.
57
+ */
58
+ const layerSyncOnly = (script) => {
59
+ const tCalls = Ref.makeUnsafe([]);
60
+ const sCalls = Ref.makeUnsafe([]);
61
+ return {
62
+ layer: Layer.effect(Transcriber, makeService(script, {
63
+ transcribe: (req) => Ref.update(tCalls, (xs) => [...xs, req]),
64
+ stream: (req) => Ref.update(sCalls, (xs) => [...xs, req])
65
+ })),
66
+ recorder: Effect.gen(function* () {
67
+ return {
68
+ transcribeCalls: yield* Ref.get(tCalls),
69
+ streamCalls: yield* Ref.get(sCalls)
70
+ };
71
+ })
72
+ };
73
+ };
74
+ //#endregion
75
+ export { layer, layerSyncOnly };
76
+
77
+ //# sourceMappingURL=MockTranscriber.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MockTranscriber.mjs","names":["AiError.InvalidRequest"],"sources":["../../src/testing/MockTranscriber.ts"],"sourcesContent":["import { Effect, Layer, Ref, Stream } from \"effect\"\nimport * as AiError from \"../domain/AiError.js\"\nimport type { TranscriptEvent, TranscriptResult } from \"../domain/Transcript.js\"\nimport {\n SttStreaming,\n Transcriber,\n type CommonStreamTranscribeRequest,\n type CommonTranscribeRequest,\n type TranscriberService,\n} from \"../transcriber/Transcriber.js\"\n\n/**\n * Recorder of every call made to the mock.\n */\nexport type MockTranscriberRecorder = {\n readonly transcribeCalls: ReadonlyArray<CommonTranscribeRequest>\n readonly streamCalls: ReadonlyArray<CommonStreamTranscribeRequest>\n}\n\nexport type MockTranscriberScript = {\n /** One result per `transcribe` call, consumed in order. */\n readonly transcripts?: ReadonlyArray<TranscriptResult>\n /** One event-list per `streamTranscriptionFrom` call, consumed in order. */\n readonly streams?: ReadonlyArray<ReadonlyArray<TranscriptEvent>>\n}\n\nconst makeService = (\n script: MockTranscriberScript,\n record: {\n readonly transcribe: (req: CommonTranscribeRequest) => Effect.Effect<void>\n readonly stream: (req: CommonStreamTranscribeRequest) => Effect.Effect<void>\n },\n) =>\n Effect.gen(function* () {\n const tCursor = yield* Ref.make(0)\n const sCursor = yield* Ref.make(0)\n const service: TranscriberService = {\n transcribe: (request) =>\n Effect.gen(function* () {\n yield* record.transcribe(request)\n const i = yield* Ref.getAndUpdate(tCursor, (n) => n + 1)\n const scripted = script.transcripts ?? []\n if (i >= scripted.length) {\n return yield* Effect.fail(\n new AiError.InvalidRequest({\n provider: \"mock\",\n raw: `MockTranscriber exhausted: ${scripted.length} transcripts scripted, but call ${i + 1} was made`,\n }),\n )\n }\n return scripted[i]!\n }),\n streamTranscriptionFrom: <E, R>(\n audioIn: Stream.Stream<Uint8Array, E, R>,\n request: CommonStreamTranscribeRequest,\n ): Stream.Stream<TranscriptEvent, AiError.AiError | E, R> =>\n Stream.unwrap(\n Effect.gen(function* () {\n yield* record.stream(request)\n const i = yield* Ref.getAndUpdate(sCursor, (n) => n + 1)\n const scripted = script.streams ?? []\n if (i >= scripted.length) {\n const exhausted: Stream.Stream<TranscriptEvent, AiError.AiError | E, R> = Stream.fail(\n new AiError.InvalidRequest({\n provider: \"mock\",\n raw: `MockTranscriber exhausted: ${scripted.length} streams scripted, but call ${i + 1} was made`,\n }),\n )\n return exhausted\n }\n // Drain the input audio fully before emitting the scripted events,\n // so consumers can assert on what bytes were pushed.\n return Stream.drain(audioIn).pipe(Stream.concat(Stream.fromIterable(scripted[i]!)))\n }),\n ),\n }\n return service\n })\n\n/**\n * Returns a Layer that provides both the `Transcriber` service and the\n * `SttStreaming` capability marker. Use when the code under test calls\n * `streamTranscriptionFrom`.\n */\nexport const layer = (\n script: MockTranscriberScript,\n): {\n readonly layer: Layer.Layer<Transcriber | SttStreaming>\n readonly recorder: Effect.Effect<MockTranscriberRecorder>\n} => {\n const tCalls = Ref.makeUnsafe<ReadonlyArray<CommonTranscribeRequest>>([])\n const sCalls = Ref.makeUnsafe<ReadonlyArray<CommonStreamTranscribeRequest>>([])\n const transcriberLayer = Layer.effect(\n Transcriber,\n makeService(script, {\n transcribe: (req) => Ref.update(tCalls, (xs) => [...xs, req]),\n stream: (req) => Ref.update(sCalls, (xs) => [...xs, req]),\n }),\n )\n const live = Layer.merge(transcriberLayer, Layer.succeed(SttStreaming, undefined))\n return {\n layer: live,\n recorder: Effect.gen(function* () {\n const transcribeCalls = yield* Ref.get(tCalls)\n const streamCalls = yield* Ref.get(sCalls)\n return { transcribeCalls, streamCalls }\n }),\n }\n}\n\n/**\n * Variant that omits the `SttStreaming` marker — use to test that\n * consumers calling `streamTranscriptionFrom` fail to compile against\n * a non-streaming provider.\n */\nexport const layerSyncOnly = (\n script: MockTranscriberScript,\n): {\n readonly layer: Layer.Layer<Transcriber>\n readonly recorder: Effect.Effect<MockTranscriberRecorder>\n} => {\n const tCalls = Ref.makeUnsafe<ReadonlyArray<CommonTranscribeRequest>>([])\n const sCalls = Ref.makeUnsafe<ReadonlyArray<CommonStreamTranscribeRequest>>([])\n const live = Layer.effect(\n Transcriber,\n makeService(script, {\n transcribe: (req) => Ref.update(tCalls, (xs) => [...xs, req]),\n stream: (req) => Ref.update(sCalls, (xs) => [...xs, req]),\n }),\n )\n return {\n layer: live,\n recorder: Effect.gen(function* () {\n const transcribeCalls = yield* Ref.get(tCalls)\n const streamCalls = yield* Ref.get(sCalls)\n return { transcribeCalls, streamCalls }\n }),\n }\n}\n"],"mappings":";;;;AA0BA,MAAM,eACJ,QACA,WAKA,OAAO,IAAI,aAAa;CACtB,MAAM,UAAU,OAAO,IAAI,KAAK,EAAE;CAClC,MAAM,UAAU,OAAO,IAAI,KAAK,EAAE;AAyClC,QAAO;EAvCL,aAAa,YACX,OAAO,IAAI,aAAa;AACtB,UAAO,OAAO,WAAW,QAAQ;GACjC,MAAM,IAAI,OAAO,IAAI,aAAa,UAAU,MAAM,IAAI,EAAE;GACxD,MAAM,WAAW,OAAO,eAAe,EAAE;AACzC,OAAI,KAAK,SAAS,OAChB,QAAO,OAAO,OAAO,KACnB,IAAIA,eAAuB;IACzB,UAAU;IACV,KAAK,8BAA8B,SAAS,OAAO,kCAAkC,IAAI,EAAE;IAC5F,CAAC,CACH;AAEH,UAAO,SAAS;IAChB;EACJ,0BACE,SACA,YAEA,OAAO,OACL,OAAO,IAAI,aAAa;AACtB,UAAO,OAAO,OAAO,QAAQ;GAC7B,MAAM,IAAI,OAAO,IAAI,aAAa,UAAU,MAAM,IAAI,EAAE;GACxD,MAAM,WAAW,OAAO,WAAW,EAAE;AACrC,OAAI,KAAK,SAAS,OAOhB,QAN0E,OAAO,KAC/E,IAAIA,eAAuB;IACzB,UAAU;IACV,KAAK,8BAA8B,SAAS,OAAO,8BAA8B,IAAI,EAAE;IACxF,CAAC,CAEY;AAIlB,UAAO,OAAO,MAAM,QAAQ,CAAC,KAAK,OAAO,OAAO,OAAO,aAAa,SAAS,GAAI,CAAC,CAAC;IACnF,CACH;EAES;EACd;;;;;;AAOJ,MAAa,SACX,WAIG;CACH,MAAM,SAAS,IAAI,WAAmD,EAAE,CAAC;CACzE,MAAM,SAAS,IAAI,WAAyD,EAAE,CAAC;CAC/E,MAAM,mBAAmB,MAAM,OAC7B,aACA,YAAY,QAAQ;EAClB,aAAa,QAAQ,IAAI,OAAO,SAAS,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC;EAC7D,SAAS,QAAQ,IAAI,OAAO,SAAS,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC;EAC1D,CAAC,CACH;AAED,QAAO;EACL,OAFW,MAAM,MAAM,kBAAkB,MAAM,QAAQ,cAAc,KAAA,EAAU,CAEpE;EACX,UAAU,OAAO,IAAI,aAAa;AAGhC,UAAO;IAAE,iBAAA,OAFsB,IAAI,IAAI,OAAO;IAEpB,aAAA,OADC,IAAI,IAAI,OAAO;IACH;IACvC;EACH;;;;;;;AAQH,MAAa,iBACX,WAIG;CACH,MAAM,SAAS,IAAI,WAAmD,EAAE,CAAC;CACzE,MAAM,SAAS,IAAI,WAAyD,EAAE,CAAC;AAQ/E,QAAO;EACL,OARW,MAAM,OACjB,aACA,YAAY,QAAQ;GAClB,aAAa,QAAQ,IAAI,OAAO,SAAS,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC;GAC7D,SAAS,QAAQ,IAAI,OAAO,SAAS,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC;GAC1D,CAAC,CAGS;EACX,UAAU,OAAO,IAAI,aAAa;AAGhC,UAAO;IAAE,iBAAA,OAFsB,IAAI,IAAI,OAAO;IAEpB,aAAA,OADC,IAAI,IAAI,OAAO;IACH;IACvC;EACH"}
@@ -1,4 +1,4 @@
1
- import { d as Item, o as FunctionCall } from "../Items-CB8Bo3FI.mjs";
1
+ import { d as Item, o as FunctionCall } from "../Items-Hg5AsYxl.mjs";
2
2
  import { ToolResult } from "./Outcome.mjs";
3
3
 
4
4
  //#region src/tool/HistoryCheck.d.ts
@@ -1,4 +1,4 @@
1
- import { o as FunctionCall, s as FunctionCallOutput } from "../Items-CB8Bo3FI.mjs";
1
+ import { o as FunctionCall, s as FunctionCallOutput } from "../Items-Hg5AsYxl.mjs";
2
2
  import { Data } from "effect";
3
3
  import * as _$effect_Unify0 from "effect/Unify";
4
4
 
@@ -1,4 +1,4 @@
1
- import { o as FunctionCall } from "../Items-CB8Bo3FI.mjs";
1
+ import { o as FunctionCall } from "../Items-Hg5AsYxl.mjs";
2
2
  import { ToolResult } from "./Outcome.mjs";
3
3
  import { ToolEvent } from "./ToolEvent.mjs";
4
4
  import { Effect, Queue, Scope, Stream } from "effect";
@@ -1,2 +1,2 @@
1
- import { a as Tool, c as ToolInputSchema, d as fromEffectSchema, f as isStreamingTool, h as toDescriptors, i as StreamingTool, m as streaming, n as AnyPlainTool, o as ToolDescriptor, p as make, r as AnyStreamingTool, s as ToolError, t as AnyKindTool, u as execute } from "../Tool-DjVufH7i.mjs";
1
+ import { a as Tool, c as ToolInputSchema, d as fromEffectSchema, f as isStreamingTool, h as toDescriptors, i as StreamingTool, m as streaming, n as AnyPlainTool, o as ToolDescriptor, p as make, r as AnyStreamingTool, s as ToolError, t as AnyKindTool, u as execute } from "../Tool-B8B5qVEy.mjs";
2
2
  export { AnyKindTool, AnyPlainTool, AnyStreamingTool, StreamingTool, Tool, ToolDescriptor, ToolError, ToolInputSchema, execute, fromEffectSchema, isStreamingTool, make, streaming, toDescriptors };
@@ -1,5 +1,5 @@
1
- import { o as FunctionCall } from "../Items-CB8Bo3FI.mjs";
2
- import { a as Tool, i as StreamingTool, o as ToolDescriptor, t as AnyKindTool } from "../Tool-DjVufH7i.mjs";
1
+ import { o as FunctionCall } from "../Items-Hg5AsYxl.mjs";
2
+ import { a as Tool, i as StreamingTool, o as ToolDescriptor, t as AnyKindTool } from "../Tool-B8B5qVEy.mjs";
3
3
  import { Event } from "../loop/Loop.mjs";
4
4
  import { ToolResult } from "./Outcome.mjs";
5
5
  import { ToolEvent } from "./ToolEvent.mjs";
@@ -0,0 +1,101 @@
1
+ import { t as AiError } from "../AiError-csR8Bhxx.mjs";
2
+ import { a as AudioSource, r as AudioFormat } from "../Audio-BfCTGnH3.mjs";
3
+ import { TranscriptEvent, TranscriptResult } from "../domain/Transcript.mjs";
4
+ import { Context, Effect, Stream } from "effect";
5
+
6
+ //#region src/transcriber/Transcriber.d.ts
7
+ declare namespace Transcriber_d_exports {
8
+ export { CommonStreamTranscribeRequest, CommonTranscribeRequest, SttStreaming, Transcriber, TranscriberService, streamTranscriptionFrom, transcribe };
9
+ }
10
+ /**
11
+ * Cross-provider sync transcription request. Provider-specific
12
+ * extensions (Deepgram `keyterm[]`, ElevenLabs `diarize`, Google
13
+ * `adaptation`, …) live on each provider's typed request which extends
14
+ * this and narrows `model`.
15
+ */
16
+ type CommonTranscribeRequest = {
17
+ readonly audio: AudioSource; /** Model identifier. Each provider narrows to its typed literal union. */
18
+ readonly model: string; /** ISO-639-1 / BCP-47. Omit for autodetection (where supported). */
19
+ readonly language?: string;
20
+ /**
21
+ * Vocab biasing. Single-string covers OpenAI/Whisper-style prompts;
22
+ * `terms[]` covers Deepgram `keyterm`, Google adaptation phrases, AWS
23
+ * `vocabularyName`. Providers ignore what they don't support.
24
+ */
25
+ readonly prompt?: string | {
26
+ readonly terms: ReadonlyArray<string>;
27
+ };
28
+ readonly diarization?: boolean;
29
+ readonly wordTimestamps?: boolean;
30
+ };
31
+ /**
32
+ * Streaming-transcription request. `inputFormat` declares what the
33
+ * bytes in the input stream will look like — providers reject
34
+ * mismatches at stream startup with `AiError.InvalidRequest`.
35
+ */
36
+ type CommonStreamTranscribeRequest = Omit<CommonTranscribeRequest, "audio"> & {
37
+ readonly inputFormat: AudioFormat;
38
+ readonly interimResults?: boolean;
39
+ readonly vadEvents?: boolean;
40
+ };
41
+ type TranscriberService = {
42
+ /**
43
+ * One-shot transcription. Universal — AWS Transcribe (which has no
44
+ * native sync endpoint) emulates this by draining a streaming session
45
+ * internally.
46
+ */
47
+ readonly transcribe: (request: CommonTranscribeRequest) => Effect.Effect<TranscriptResult, AiError>;
48
+ /**
49
+ * Live transcription as a Stream transformer. Consumes audio bytes
50
+ * from `audioIn`; emits `TranscriptEvent`s as they arrive. The
51
+ * underlying WS / gRPC connection is acquired on first pull and
52
+ * released when the output stream is finalized (success, failure, or
53
+ * interruption) via `Stream.scoped` — no explicit Scope handling at
54
+ * the call site.
55
+ *
56
+ * Gated by the `SttStreaming` capability marker on the top-level
57
+ * helper — providers without streaming-STT support don't ship the
58
+ * marker, so calls fail at `Effect.provide` with a type error.
59
+ */
60
+ readonly streamTranscriptionFrom: <E, R>(audioIn: Stream.Stream<Uint8Array, E, R>, request: CommonStreamTranscribeRequest) => Stream.Stream<TranscriptEvent, AiError | E, R>;
61
+ };
62
+ declare const Transcriber_base: Context.ServiceClass<Transcriber, "@betalyra/effect-uai/Transcriber", TranscriberService>;
63
+ declare class Transcriber extends Transcriber_base {}
64
+ declare const SttStreaming_base: Context.ServiceClass<SttStreaming, "@betalyra/effect-uai/capability/SttStreaming", void>;
65
+ /**
66
+ * Capability marker — provided by provider layers whose
67
+ * `streamTranscriptionFrom` is wired up at the wire level. Azure does
68
+ * not ship it (streaming-STT is SDK-internal). Calling
69
+ * `streamTranscriptionFrom` while only Azure's Layer is in scope fails
70
+ * at `Effect.provide` with a type error, not at runtime.
71
+ *
72
+ * Phantom — the value is `void`; providers register with
73
+ * `Layer.succeed(SttStreaming, undefined)`.
74
+ */
75
+ declare class SttStreaming extends SttStreaming_base {}
76
+ /** One-shot transcription. */
77
+ declare const transcribe: (request: CommonTranscribeRequest) => Effect.Effect<TranscriptResult, AiError, Transcriber>;
78
+ /**
79
+ * Live transcription. Dual-arity: pipeable (data-last) and direct
80
+ * (data-first). Requires `SttStreaming` in R — providers without
81
+ * streaming support are a type error at provide time.
82
+ *
83
+ * @example
84
+ * ```ts
85
+ * // Pipeable — composes with other Stream operators
86
+ * mic.frames.pipe(
87
+ * Transcriber.streamTranscriptionFrom(req),
88
+ * Stream.filter((e) => e._tag === "final"),
89
+ * )
90
+ *
91
+ * // Direct
92
+ * Transcriber.streamTranscriptionFrom(mic.frames, req)
93
+ * ```
94
+ */
95
+ declare const streamTranscriptionFrom: {
96
+ (request: CommonStreamTranscribeRequest): <E, R>(audioIn: Stream.Stream<Uint8Array, E, R>) => Stream.Stream<TranscriptEvent, AiError | E, R | Transcriber | SttStreaming>;
97
+ <E, R>(audioIn: Stream.Stream<Uint8Array, E, R>, request: CommonStreamTranscribeRequest): Stream.Stream<TranscriptEvent, AiError | E, R | Transcriber | SttStreaming>;
98
+ };
99
+ //#endregion
100
+ export { CommonStreamTranscribeRequest, CommonTranscribeRequest, SttStreaming, Transcriber, TranscriberService, streamTranscriptionFrom, Transcriber_d_exports as t, transcribe };
101
+ //# sourceMappingURL=Transcriber.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Transcriber.d.mts","names":[],"sources":["../../src/transcriber/Transcriber.ts"],"mappings":";;;;;;;;;;;;;;;KAWY,uBAAA;EAAA,SACD,KAAA,EAAO,WAAA;WAEP,KAAA;WAEA,QAAA;EALC;;;;;EAAA,SAWD,MAAA;IAAA,SAA6B,KAAA,EAAO,aAAA;EAAA;EAAA,SACpC,WAAA;EAAA,SACA,cAAA;AAAA;;;;;AAQX;KAAY,6BAAA,GAAgC,IAAA,CAAK,uBAAA;EAAA,SACtC,WAAA,EAAa,WAAA;EAAA,SACb,cAAA;EAAA,SACA,SAAA;AAAA;AAAA,KAGC,kBAAA;EALuB;;;;;EAAA,SAWxB,UAAA,GACP,OAAA,EAAS,uBAAA,KACN,MAAA,CAAO,MAAA,CAAO,gBAAA,EAAkB,OAAA;EAX5B;;;AAGX;;;;;;;;;EAHW,SAwBA,uBAAA,SACP,OAAA,EAAS,MAAA,CAAO,MAAA,CAAO,UAAA,EAAY,CAAA,EAAG,CAAA,GACtC,OAAA,EAAS,6BAAA,KACN,MAAA,CAAO,MAAA,CAAO,eAAA,EAAiB,OAAA,GAAkB,CAAA,EAAG,CAAA;AAAA;AAAA,cAC1D,gBAAA;cAEY,WAAA,SAAoB,gBAAA;AAAA,cAE7B,iBAAA;;;;;;;;;;;cAYS,YAAA,SAAqB,iBAAA;;cAKrB,UAAA,GACX,OAAA,EAAS,uBAAA,KACR,MAAA,CAAO,MAAA,CAAO,gBAAA,EAAkB,OAAA,EAAiB,WAAA;;;;;;;;;;;;;;;;;;cAoBvC,uBAAA;EAAA,CAET,OAAA,EAAS,6BAAA,UAET,OAAA,EAAS,MAAA,CAAO,MAAA,CAAO,UAAA,EAAY,CAAA,EAAG,CAAA,MACnC,MAAA,CAAO,MAAA,CAAO,eAAA,EAAiB,OAAA,GAAkB,CAAA,EAAG,CAAA,GAAI,WAAA,GAAc,YAAA;EAAA,OAEzE,OAAA,EAAS,MAAA,CAAO,MAAA,CAAO,UAAA,EAAY,CAAA,EAAG,CAAA,GACtC,OAAA,EAAS,6BAAA,GACR,MAAA,CAAO,MAAA,CAAO,eAAA,EAAiB,OAAA,GAAkB,CAAA,EAAG,CAAA,GAAI,WAAA,GAAc,YAAA;AAAA"}
@@ -0,0 +1,49 @@
1
+ import { n as __exportAll } from "../chunk-uyGKjUfl.mjs";
2
+ import { Context, Effect, Function, Stream } from "effect";
3
+ //#region src/transcriber/Transcriber.ts
4
+ var Transcriber_exports = /* @__PURE__ */ __exportAll({
5
+ SttStreaming: () => SttStreaming,
6
+ Transcriber: () => Transcriber,
7
+ streamTranscriptionFrom: () => streamTranscriptionFrom,
8
+ transcribe: () => transcribe
9
+ });
10
+ var Transcriber = class extends Context.Service()("@betalyra/effect-uai/Transcriber") {};
11
+ /**
12
+ * Capability marker — provided by provider layers whose
13
+ * `streamTranscriptionFrom` is wired up at the wire level. Azure does
14
+ * not ship it (streaming-STT is SDK-internal). Calling
15
+ * `streamTranscriptionFrom` while only Azure's Layer is in scope fails
16
+ * at `Effect.provide` with a type error, not at runtime.
17
+ *
18
+ * Phantom — the value is `void`; providers register with
19
+ * `Layer.succeed(SttStreaming, undefined)`.
20
+ */
21
+ var SttStreaming = class extends Context.Service()("@betalyra/effect-uai/capability/SttStreaming") {};
22
+ /** One-shot transcription. */
23
+ const transcribe = (request) => Effect.flatMap(Transcriber.asEffect(), (t) => t.transcribe(request));
24
+ /**
25
+ * Live transcription. Dual-arity: pipeable (data-last) and direct
26
+ * (data-first). Requires `SttStreaming` in R — providers without
27
+ * streaming support are a type error at provide time.
28
+ *
29
+ * @example
30
+ * ```ts
31
+ * // Pipeable — composes with other Stream operators
32
+ * mic.frames.pipe(
33
+ * Transcriber.streamTranscriptionFrom(req),
34
+ * Stream.filter((e) => e._tag === "final"),
35
+ * )
36
+ *
37
+ * // Direct
38
+ * Transcriber.streamTranscriptionFrom(mic.frames, req)
39
+ * ```
40
+ */
41
+ const streamTranscriptionFrom = Function.dual(2, (audioIn, request) => Stream.unwrap(Effect.gen(function* () {
42
+ const t = yield* Transcriber.asEffect();
43
+ yield* SttStreaming.asEffect();
44
+ return t.streamTranscriptionFrom(audioIn, request);
45
+ })));
46
+ //#endregion
47
+ export { SttStreaming, Transcriber, streamTranscriptionFrom, Transcriber_exports as t, transcribe };
48
+
49
+ //# sourceMappingURL=Transcriber.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Transcriber.mjs","names":[],"sources":["../../src/transcriber/Transcriber.ts"],"sourcesContent":["import { Context, Effect, Function, Stream } from \"effect\"\nimport * as AiError from \"../domain/AiError.js\"\nimport type { AudioFormat, AudioSource } from \"../domain/Audio.js\"\nimport type { TranscriptEvent, TranscriptResult } from \"../domain/Transcript.js\"\n\n/**\n * Cross-provider sync transcription request. Provider-specific\n * extensions (Deepgram `keyterm[]`, ElevenLabs `diarize`, Google\n * `adaptation`, …) live on each provider's typed request which extends\n * this and narrows `model`.\n */\nexport type CommonTranscribeRequest = {\n readonly audio: AudioSource\n /** Model identifier. Each provider narrows to its typed literal union. */\n readonly model: string\n /** ISO-639-1 / BCP-47. Omit for autodetection (where supported). */\n readonly language?: string\n /**\n * Vocab biasing. Single-string covers OpenAI/Whisper-style prompts;\n * `terms[]` covers Deepgram `keyterm`, Google adaptation phrases, AWS\n * `vocabularyName`. Providers ignore what they don't support.\n */\n readonly prompt?: string | { readonly terms: ReadonlyArray<string> }\n readonly diarization?: boolean\n readonly wordTimestamps?: boolean\n}\n\n/**\n * Streaming-transcription request. `inputFormat` declares what the\n * bytes in the input stream will look like — providers reject\n * mismatches at stream startup with `AiError.InvalidRequest`.\n */\nexport type CommonStreamTranscribeRequest = Omit<CommonTranscribeRequest, \"audio\"> & {\n readonly inputFormat: AudioFormat\n readonly interimResults?: boolean\n readonly vadEvents?: boolean\n}\n\nexport type TranscriberService = {\n /**\n * One-shot transcription. Universal — AWS Transcribe (which has no\n * native sync endpoint) emulates this by draining a streaming session\n * internally.\n */\n readonly transcribe: (\n request: CommonTranscribeRequest,\n ) => Effect.Effect<TranscriptResult, AiError.AiError>\n /**\n * Live transcription as a Stream transformer. Consumes audio bytes\n * from `audioIn`; emits `TranscriptEvent`s as they arrive. The\n * underlying WS / gRPC connection is acquired on first pull and\n * released when the output stream is finalized (success, failure, or\n * interruption) via `Stream.scoped` — no explicit Scope handling at\n * the call site.\n *\n * Gated by the `SttStreaming` capability marker on the top-level\n * helper — providers without streaming-STT support don't ship the\n * marker, so calls fail at `Effect.provide` with a type error.\n */\n readonly streamTranscriptionFrom: <E, R>(\n audioIn: Stream.Stream<Uint8Array, E, R>,\n request: CommonStreamTranscribeRequest,\n ) => Stream.Stream<TranscriptEvent, AiError.AiError | E, R>\n}\n\nexport class Transcriber extends Context.Service<Transcriber, TranscriberService>()(\n \"@betalyra/effect-uai/Transcriber\",\n) {}\n\n/**\n * Capability marker — provided by provider layers whose\n * `streamTranscriptionFrom` is wired up at the wire level. Azure does\n * not ship it (streaming-STT is SDK-internal). Calling\n * `streamTranscriptionFrom` while only Azure's Layer is in scope fails\n * at `Effect.provide` with a type error, not at runtime.\n *\n * Phantom — the value is `void`; providers register with\n * `Layer.succeed(SttStreaming, undefined)`.\n */\nexport class SttStreaming extends Context.Service<SttStreaming, void>()(\n \"@betalyra/effect-uai/capability/SttStreaming\",\n) {}\n\n/** One-shot transcription. */\nexport const transcribe = (\n request: CommonTranscribeRequest,\n): Effect.Effect<TranscriptResult, AiError.AiError, Transcriber> =>\n Effect.flatMap(Transcriber.asEffect(), (t) => t.transcribe(request))\n\n/**\n * Live transcription. Dual-arity: pipeable (data-last) and direct\n * (data-first). Requires `SttStreaming` in R — providers without\n * streaming support are a type error at provide time.\n *\n * @example\n * ```ts\n * // Pipeable — composes with other Stream operators\n * mic.frames.pipe(\n * Transcriber.streamTranscriptionFrom(req),\n * Stream.filter((e) => e._tag === \"final\"),\n * )\n *\n * // Direct\n * Transcriber.streamTranscriptionFrom(mic.frames, req)\n * ```\n */\nexport const streamTranscriptionFrom: {\n (\n request: CommonStreamTranscribeRequest,\n ): <E, R>(\n audioIn: Stream.Stream<Uint8Array, E, R>,\n ) => Stream.Stream<TranscriptEvent, AiError.AiError | E, R | Transcriber | SttStreaming>\n <E, R>(\n audioIn: Stream.Stream<Uint8Array, E, R>,\n request: CommonStreamTranscribeRequest,\n ): Stream.Stream<TranscriptEvent, AiError.AiError | E, R | Transcriber | SttStreaming>\n} = Function.dual(\n 2,\n <E, R>(audioIn: Stream.Stream<Uint8Array, E, R>, request: CommonStreamTranscribeRequest) =>\n Stream.unwrap(\n Effect.gen(function* () {\n const t = yield* Transcriber.asEffect()\n yield* SttStreaming.asEffect()\n return t.streamTranscriptionFrom(audioIn, request)\n }),\n ),\n)\n"],"mappings":";;;;;;;;;AAiEA,IAAa,cAAb,cAAiC,QAAQ,SAA0C,CACjF,mCACD,CAAC;;;;;;;;;;;AAYF,IAAa,eAAb,cAAkC,QAAQ,SAA6B,CACrE,+CACD,CAAC;;AAGF,MAAa,cACX,YAEA,OAAO,QAAQ,YAAY,UAAU,GAAG,MAAM,EAAE,WAAW,QAAQ,CAAC;;;;;;;;;;;;;;;;;;AAmBtE,MAAa,0BAUT,SAAS,KACX,IACO,SAA0C,YAC/C,OAAO,OACL,OAAO,IAAI,aAAa;CACtB,MAAM,IAAI,OAAO,YAAY,UAAU;AACvC,QAAO,aAAa,UAAU;AAC9B,QAAO,EAAE,wBAAwB,SAAS,QAAQ;EAClD,CACH,CACJ"}
@@ -0,0 +1 @@
1
+ export { };
@@ -0,0 +1,130 @@
1
+ import { streamTranscriptionFrom, transcribe } from "./Transcriber.mjs";
2
+ import { i as it, n as globalExpect, r as describe, t as import_dist } from "../dist-DV5ISja1.mjs";
3
+ import { layer, layerSyncOnly } from "../testing/MockTranscriber.mjs";
4
+ import { Effect, Stream } from "effect";
5
+ //#region src/transcriber/Transcriber.test.ts
6
+ describe("Transcriber.transcribe", () => {
7
+ it("returns the scripted TranscriptResult", async () => {
8
+ const mock = layer({ transcripts: [{
9
+ text: "hello world",
10
+ durationSeconds: 1.23
11
+ }] });
12
+ const program = transcribe({
13
+ audio: {
14
+ _tag: "bytes",
15
+ bytes: new Uint8Array([0]),
16
+ mimeType: "audio/wav"
17
+ },
18
+ model: "mock-stt"
19
+ });
20
+ const result = await Effect.runPromise(program.pipe(Effect.provide(mock.layer)));
21
+ globalExpect(result.text).toBe("hello world");
22
+ globalExpect(result.durationSeconds).toBe(1.23);
23
+ });
24
+ it("records each transcribe call", async () => {
25
+ const mock = layer({ transcripts: [{ text: "a" }, { text: "b" }] });
26
+ const program = Effect.gen(function* () {
27
+ yield* transcribe({
28
+ audio: {
29
+ _tag: "bytes",
30
+ bytes: new Uint8Array([1]),
31
+ mimeType: "audio/wav"
32
+ },
33
+ model: "m1"
34
+ });
35
+ yield* transcribe({
36
+ audio: {
37
+ _tag: "bytes",
38
+ bytes: new Uint8Array([2]),
39
+ mimeType: "audio/wav"
40
+ },
41
+ model: "m2"
42
+ });
43
+ return yield* mock.recorder;
44
+ });
45
+ globalExpect((await Effect.runPromise(program.pipe(Effect.provide(mock.layer)))).transcribeCalls.map((c) => c.model)).toEqual(["m1", "m2"]);
46
+ });
47
+ });
48
+ describe("Transcriber capability marker (compile-time)", () => {
49
+ const sttReq = {
50
+ model: "mock-stt",
51
+ inputFormat: {
52
+ container: "raw",
53
+ encoding: "pcm_s16le",
54
+ sampleRate: 16e3
55
+ }
56
+ };
57
+ it("requires `SttStreaming` on the R channel of streamTranscriptionFrom", () => {
58
+ (0, import_dist.expectTypeOf)(Stream.fromIterable([new Uint8Array([0])]).pipe(streamTranscriptionFrom(sttReq))).toEqualTypeOf();
59
+ });
60
+ it("does NOT require `SttStreaming` for sync `transcribe`", () => {
61
+ (0, import_dist.expectTypeOf)(transcribe({
62
+ audio: {
63
+ _tag: "bytes",
64
+ bytes: new Uint8Array([0]),
65
+ mimeType: "audio/wav"
66
+ },
67
+ model: "m"
68
+ })).toEqualTypeOf();
69
+ });
70
+ it("a sync-only layer leaves `SttStreaming` unsatisfied in R", () => {
71
+ const syncOnly = layerSyncOnly({});
72
+ const events = Stream.fromIterable([new Uint8Array([0])]).pipe(streamTranscriptionFrom(sttReq));
73
+ (0, import_dist.expectTypeOf)(Stream.runDrain(events).pipe(Effect.provide(syncOnly.layer))).toEqualTypeOf();
74
+ });
75
+ it("a full layer (with marker) clears R to never", () => {
76
+ const fullMock = layer({ streams: [[]] });
77
+ const events = Stream.fromIterable([new Uint8Array([0])]).pipe(streamTranscriptionFrom(sttReq));
78
+ (0, import_dist.expectTypeOf)(Stream.runDrain(events).pipe(Effect.provide(fullMock.layer))).toEqualTypeOf();
79
+ });
80
+ });
81
+ describe("Transcriber.streamTranscriptionFrom", () => {
82
+ const sttReq = {
83
+ model: "mock-stt",
84
+ inputFormat: {
85
+ container: "raw",
86
+ encoding: "pcm_s16le",
87
+ sampleRate: 16e3
88
+ }
89
+ };
90
+ it("emits scripted events after draining the input audio stream", async () => {
91
+ const mock = layer({ streams: [[{
92
+ _tag: "partial",
93
+ text: "hello"
94
+ }, {
95
+ _tag: "final",
96
+ text: "hello world"
97
+ }]] });
98
+ const events = Stream.fromIterable([new Uint8Array([
99
+ 0,
100
+ 1,
101
+ 2
102
+ ]), new Uint8Array([
103
+ 3,
104
+ 4,
105
+ 5
106
+ ])]).pipe(streamTranscriptionFrom(sttReq));
107
+ globalExpect(await Effect.runPromise(Stream.runCollect(events).pipe(Effect.provide(mock.layer)))).toEqual([{
108
+ _tag: "partial",
109
+ text: "hello"
110
+ }, {
111
+ _tag: "final",
112
+ text: "hello world"
113
+ }]);
114
+ });
115
+ it("works data-first (direct call) as well as pipeable (data-last)", async () => {
116
+ const mock = layer({ streams: [[{
117
+ _tag: "final",
118
+ text: "x"
119
+ }]] });
120
+ const events = streamTranscriptionFrom(Stream.fromIterable([new Uint8Array([0])]), sttReq);
121
+ globalExpect(await Effect.runPromise(Stream.runCollect(events).pipe(Effect.provide(mock.layer)))).toEqual([{
122
+ _tag: "final",
123
+ text: "x"
124
+ }]);
125
+ });
126
+ });
127
+ //#endregion
128
+ export {};
129
+
130
+ //# sourceMappingURL=Transcriber.test.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Transcriber.test.mjs","names":["MockTranscriber.layer","Transcriber.transcribe","Transcriber.streamTranscriptionFrom","MockTranscriber.layerSyncOnly"],"sources":["../../src/transcriber/Transcriber.test.ts"],"sourcesContent":["import { Effect, Stream } from \"effect\"\nimport { describe, expect, expectTypeOf, it } from \"vitest\"\nimport type * as AiError from \"../domain/AiError.js\"\nimport type { TranscriptEvent, TranscriptResult } from \"../domain/Transcript.js\"\nimport * as MockTranscriber from \"../testing/MockTranscriber.js\"\nimport * as Transcriber from \"./Transcriber.js\"\n\ndescribe(\"Transcriber.transcribe\", () => {\n it(\"returns the scripted TranscriptResult\", async () => {\n const mock = MockTranscriber.layer({\n transcripts: [{ text: \"hello world\", durationSeconds: 1.23 }],\n })\n const program = Transcriber.transcribe({\n audio: { _tag: \"bytes\", bytes: new Uint8Array([0]), mimeType: \"audio/wav\" },\n model: \"mock-stt\",\n })\n const result = await Effect.runPromise(program.pipe(Effect.provide(mock.layer)))\n expect(result.text).toBe(\"hello world\")\n expect(result.durationSeconds).toBe(1.23)\n })\n\n it(\"records each transcribe call\", async () => {\n const mock = MockTranscriber.layer({\n transcripts: [{ text: \"a\" }, { text: \"b\" }],\n })\n const program = Effect.gen(function* () {\n yield* Transcriber.transcribe({\n audio: { _tag: \"bytes\", bytes: new Uint8Array([1]), mimeType: \"audio/wav\" },\n model: \"m1\",\n })\n yield* Transcriber.transcribe({\n audio: { _tag: \"bytes\", bytes: new Uint8Array([2]), mimeType: \"audio/wav\" },\n model: \"m2\",\n })\n return yield* mock.recorder\n })\n const rec = await Effect.runPromise(program.pipe(Effect.provide(mock.layer)))\n expect(rec.transcribeCalls.map((c) => c.model)).toEqual([\"m1\", \"m2\"])\n })\n})\n\ndescribe(\"Transcriber capability marker (compile-time)\", () => {\n const sttReq: Transcriber.CommonStreamTranscribeRequest = {\n model: \"mock-stt\",\n inputFormat: { container: \"raw\", encoding: \"pcm_s16le\", sampleRate: 16000 },\n }\n\n it(\"requires `SttStreaming` on the R channel of streamTranscriptionFrom\", () => {\n const audio: Stream.Stream<Uint8Array> = Stream.fromIterable([new Uint8Array([0])])\n const events = audio.pipe(Transcriber.streamTranscriptionFrom(sttReq))\n expectTypeOf(events).toEqualTypeOf<\n Stream.Stream<\n TranscriptEvent,\n AiError.AiError,\n Transcriber.Transcriber | Transcriber.SttStreaming\n >\n >()\n })\n\n it(\"does NOT require `SttStreaming` for sync `transcribe`\", () => {\n const eff = Transcriber.transcribe({\n audio: { _tag: \"bytes\", bytes: new Uint8Array([0]), mimeType: \"audio/wav\" },\n model: \"m\",\n })\n expectTypeOf(eff).toEqualTypeOf<\n Effect.Effect<TranscriptResult, AiError.AiError, Transcriber.Transcriber>\n >()\n })\n\n it(\"a sync-only layer leaves `SttStreaming` unsatisfied in R\", () => {\n const syncOnly = MockTranscriber.layerSyncOnly({})\n const audio: Stream.Stream<Uint8Array> = Stream.fromIterable([new Uint8Array([0])])\n const events = audio.pipe(Transcriber.streamTranscriptionFrom(sttReq))\n const program = Stream.runDrain(events).pipe(Effect.provide(syncOnly.layer))\n // `Transcriber` is provided by syncOnly.layer; `SttStreaming` is not.\n expectTypeOf(program).toEqualTypeOf<\n Effect.Effect<void, AiError.AiError, Transcriber.SttStreaming>\n >()\n })\n\n it(\"a full layer (with marker) clears R to never\", () => {\n const fullMock = MockTranscriber.layer({ streams: [[]] })\n const audio: Stream.Stream<Uint8Array> = Stream.fromIterable([new Uint8Array([0])])\n const events = audio.pipe(Transcriber.streamTranscriptionFrom(sttReq))\n const program = Stream.runDrain(events).pipe(Effect.provide(fullMock.layer))\n expectTypeOf(program).toEqualTypeOf<Effect.Effect<void, AiError.AiError, never>>()\n })\n})\n\ndescribe(\"Transcriber.streamTranscriptionFrom\", () => {\n const sttReq: Transcriber.CommonStreamTranscribeRequest = {\n model: \"mock-stt\",\n inputFormat: { container: \"raw\", encoding: \"pcm_s16le\", sampleRate: 16000 },\n }\n\n it(\"emits scripted events after draining the input audio stream\", async () => {\n const mock = MockTranscriber.layer({\n streams: [\n [\n { _tag: \"partial\", text: \"hello\" },\n { _tag: \"final\", text: \"hello world\" },\n ],\n ],\n })\n const audio = Stream.fromIterable([new Uint8Array([0, 1, 2]), new Uint8Array([3, 4, 5])])\n const events = audio.pipe(Transcriber.streamTranscriptionFrom(sttReq))\n const collected = await Effect.runPromise(\n Stream.runCollect(events).pipe(Effect.provide(mock.layer)),\n )\n expect(collected).toEqual([\n { _tag: \"partial\", text: \"hello\" },\n { _tag: \"final\", text: \"hello world\" },\n ])\n })\n\n it(\"works data-first (direct call) as well as pipeable (data-last)\", async () => {\n const mock = MockTranscriber.layer({\n streams: [[{ _tag: \"final\", text: \"x\" }]],\n })\n const audio = Stream.fromIterable([new Uint8Array([0])])\n const events = Transcriber.streamTranscriptionFrom(audio, sttReq)\n const out = await Effect.runPromise(Stream.runCollect(events).pipe(Effect.provide(mock.layer)))\n expect(out).toEqual([{ _tag: \"final\", text: \"x\" }])\n })\n})\n"],"mappings":"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"}