@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
+ declare namespace Transcript_d_exports {
2
+ export { TranscriptEvent, TranscriptResult, WordTimestamp, isAudioEvent, isError, isFinal, isMetadata, isPartial, isSpeechStarted, isUtteranceEnded };
3
+ }
4
+ /**
5
+ * Per-word timing + metadata. `confidence` and `speakerId` are optional
6
+ * because providers vary widely in what they emit and when (some only on
7
+ * final, some only with diarization enabled, some not at all).
8
+ */
9
+ type WordTimestamp = {
10
+ readonly text: string;
11
+ readonly startSeconds: number;
12
+ readonly endSeconds: number;
13
+ readonly confidence?: number;
14
+ readonly speakerId?: string;
15
+ readonly languageCode?: string;
16
+ };
17
+ /**
18
+ * Sync STT result. `raw` preserves the provider-specific response for
19
+ * consumers that need fields the common shape doesn't expose
20
+ * (alternatives, segments, NBest, audio events, etc.).
21
+ */
22
+ type TranscriptResult = {
23
+ readonly text: string;
24
+ readonly languageCode?: string;
25
+ readonly durationSeconds?: number;
26
+ readonly words?: ReadonlyArray<WordTimestamp>;
27
+ readonly raw?: unknown;
28
+ };
29
+ /**
30
+ * Streaming STT event union. Collapses every provider's vocabulary into
31
+ * a small set; provider-specific shapes survive on `metadata.raw`.
32
+ *
33
+ * - `partial`: interim hypothesis. `stability` is Google-only.
34
+ * - `final`: committed transcript for the current utterance / segment.
35
+ * - `speech-started` / `utterance-ended`: VAD-derived boundaries. Not
36
+ * all providers emit them (OpenAI Realtime, Google with
37
+ * `voice_activity_events`, Deepgram with `vad_events`, AssemblyAI).
38
+ * - `audio-event`: non-speech label (`(laughter)`, `(music)`) — ElevenLabs only.
39
+ * - `metadata`: opaque server-side bookkeeping (request_id, model info).
40
+ * - `error`: non-fatal provider error mid-stream. Fatal errors surface
41
+ * on the `Stream`'s error channel as `AiError.AiError`.
42
+ */
43
+ type TranscriptEvent = {
44
+ readonly _tag: "partial";
45
+ readonly text: string;
46
+ readonly words?: ReadonlyArray<WordTimestamp>;
47
+ readonly stability?: number;
48
+ } | {
49
+ readonly _tag: "final";
50
+ readonly text: string;
51
+ readonly words?: ReadonlyArray<WordTimestamp>;
52
+ readonly languageCode?: string;
53
+ } | {
54
+ readonly _tag: "speech-started";
55
+ readonly atSeconds: number;
56
+ } | {
57
+ readonly _tag: "utterance-ended";
58
+ readonly atSeconds: number;
59
+ } | {
60
+ readonly _tag: "audio-event";
61
+ readonly label: string;
62
+ readonly startSeconds: number;
63
+ readonly endSeconds: number;
64
+ } | {
65
+ readonly _tag: "metadata";
66
+ readonly raw: unknown;
67
+ } | {
68
+ readonly _tag: "error";
69
+ readonly code?: string;
70
+ readonly message: string;
71
+ };
72
+ declare const isPartial: (e: TranscriptEvent) => e is Extract<TranscriptEvent, {
73
+ _tag: "partial";
74
+ }>;
75
+ declare const isFinal: (e: TranscriptEvent) => e is Extract<TranscriptEvent, {
76
+ _tag: "final";
77
+ }>;
78
+ declare const isSpeechStarted: (e: TranscriptEvent) => e is Extract<TranscriptEvent, {
79
+ _tag: "speech-started";
80
+ }>;
81
+ declare const isUtteranceEnded: (e: TranscriptEvent) => e is Extract<TranscriptEvent, {
82
+ _tag: "utterance-ended";
83
+ }>;
84
+ declare const isAudioEvent: (e: TranscriptEvent) => e is Extract<TranscriptEvent, {
85
+ _tag: "audio-event";
86
+ }>;
87
+ declare const isMetadata: (e: TranscriptEvent) => e is Extract<TranscriptEvent, {
88
+ _tag: "metadata";
89
+ }>;
90
+ declare const isError: (e: TranscriptEvent) => e is Extract<TranscriptEvent, {
91
+ _tag: "error";
92
+ }>;
93
+ //#endregion
94
+ export { TranscriptEvent, TranscriptResult, WordTimestamp, isAudioEvent, isError, isFinal, isMetadata, isPartial, isSpeechStarted, isUtteranceEnded, Transcript_d_exports as t };
95
+ //# sourceMappingURL=Transcript.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Transcript.d.mts","names":[],"sources":["../../src/domain/Transcript.ts"],"mappings":";;;;;;;;KAKY,aAAA;EAAA,SACD,IAAA;EAAA,SACA,YAAA;EAAA,SACA,UAAA;EAAA,SACA,UAAA;EAAA,SACA,SAAA;EAAA,SACA,YAAA;AAAA;;;AANX;;;KAcY,gBAAA;EAAA,SACD,IAAA;EAAA,SACA,YAAA;EAAA,SACA,eAAA;EAAA,SACA,KAAA,GAAQ,aAAA,CAAc,aAAA;EAAA,SACtB,GAAA;AAAA;;;AALX;;;;;;;;;;;;KAsBY,eAAA;EAAA,SAEG,IAAA;EAAA,SACA,IAAA;EAAA,SACA,KAAA,GAAQ,aAAA,CAAc,aAAA;EAAA,SACtB,SAAA;AAAA;EAAA,SAGA,IAAA;EAAA,SACA,IAAA;EAAA,SACA,KAAA,GAAQ,aAAA,CAAc,aAAA;EAAA,SACtB,YAAA;AAAA;EAAA,SAEA,IAAA;EAAA,SAAiC,SAAA;AAAA;EAAA,SACjC,IAAA;EAAA,SAAkC,SAAA;AAAA;EAAA,SAElC,IAAA;EAAA,SACA,KAAA;EAAA,SACA,YAAA;EAAA,SACA,UAAA;AAAA;EAAA,SAEA,IAAA;EAAA,SAA2B,GAAA;AAAA;EAAA,SAC3B,IAAA;EAAA,SAAwB,IAAA;EAAA,SAAwB,OAAA;AAAA;AAAA,cAElD,SAAA,GAAa,CAAA,EAAG,eAAA,KAAkB,CAAA,IAAK,OAAA,CAAQ,eAAA;EAAmB,IAAA;AAAA;AAAA,cAElE,OAAA,GAAW,CAAA,EAAG,eAAA,KAAkB,CAAA,IAAK,OAAA,CAAQ,eAAA;EAAmB,IAAA;AAAA;AAAA,cAEhE,eAAA,GACX,CAAA,EAAG,eAAA,KACF,CAAA,IAAK,OAAA,CAAQ,eAAA;EAAmB,IAAA;AAAA;AAAA,cACtB,gBAAA,GACX,CAAA,EAAG,eAAA,KACF,CAAA,IAAK,OAAA,CAAQ,eAAA;EAAmB,IAAA;AAAA;AAAA,cACtB,YAAA,GACX,CAAA,EAAG,eAAA,KACF,CAAA,IAAK,OAAA,CAAQ,eAAA;EAAmB,IAAA;AAAA;AAAA,cACtB,UAAA,GACX,CAAA,EAAG,eAAA,KACF,CAAA,IAAK,OAAA,CAAQ,eAAA;EAAmB,IAAA;AAAA;AAAA,cACtB,OAAA,GAAW,CAAA,EAAG,eAAA,KAAkB,CAAA,IAAK,OAAA,CAAQ,eAAA;EAAmB,IAAA;AAAA"}
@@ -0,0 +1,22 @@
1
+ import { n as __exportAll } from "../chunk-uyGKjUfl.mjs";
2
+ //#region src/domain/Transcript.ts
3
+ var Transcript_exports = /* @__PURE__ */ __exportAll({
4
+ isAudioEvent: () => isAudioEvent,
5
+ isError: () => isError,
6
+ isFinal: () => isFinal,
7
+ isMetadata: () => isMetadata,
8
+ isPartial: () => isPartial,
9
+ isSpeechStarted: () => isSpeechStarted,
10
+ isUtteranceEnded: () => isUtteranceEnded
11
+ });
12
+ const isPartial = (e) => e._tag === "partial";
13
+ const isFinal = (e) => e._tag === "final";
14
+ const isSpeechStarted = (e) => e._tag === "speech-started";
15
+ const isUtteranceEnded = (e) => e._tag === "utterance-ended";
16
+ const isAudioEvent = (e) => e._tag === "audio-event";
17
+ const isMetadata = (e) => e._tag === "metadata";
18
+ const isError = (e) => e._tag === "error";
19
+ //#endregion
20
+ export { isAudioEvent, isError, isFinal, isMetadata, isPartial, isSpeechStarted, isUtteranceEnded, Transcript_exports as t };
21
+
22
+ //# sourceMappingURL=Transcript.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Transcript.mjs","names":[],"sources":["../../src/domain/Transcript.ts"],"sourcesContent":["/**\n * Per-word timing + metadata. `confidence` and `speakerId` are optional\n * because providers vary widely in what they emit and when (some only on\n * final, some only with diarization enabled, some not at all).\n */\nexport type WordTimestamp = {\n readonly text: string\n readonly startSeconds: number\n readonly endSeconds: number\n readonly confidence?: number\n readonly speakerId?: string\n readonly languageCode?: string\n}\n\n/**\n * Sync STT result. `raw` preserves the provider-specific response for\n * consumers that need fields the common shape doesn't expose\n * (alternatives, segments, NBest, audio events, etc.).\n */\nexport type TranscriptResult = {\n readonly text: string\n readonly languageCode?: string\n readonly durationSeconds?: number\n readonly words?: ReadonlyArray<WordTimestamp>\n readonly raw?: unknown\n}\n\n/**\n * Streaming STT event union. Collapses every provider's vocabulary into\n * a small set; provider-specific shapes survive on `metadata.raw`.\n *\n * - `partial`: interim hypothesis. `stability` is Google-only.\n * - `final`: committed transcript for the current utterance / segment.\n * - `speech-started` / `utterance-ended`: VAD-derived boundaries. Not\n * all providers emit them (OpenAI Realtime, Google with\n * `voice_activity_events`, Deepgram with `vad_events`, AssemblyAI).\n * - `audio-event`: non-speech label (`(laughter)`, `(music)`) — ElevenLabs only.\n * - `metadata`: opaque server-side bookkeeping (request_id, model info).\n * - `error`: non-fatal provider error mid-stream. Fatal errors surface\n * on the `Stream`'s error channel as `AiError.AiError`.\n */\nexport type TranscriptEvent =\n | {\n readonly _tag: \"partial\"\n readonly text: string\n readonly words?: ReadonlyArray<WordTimestamp>\n readonly stability?: number\n }\n | {\n readonly _tag: \"final\"\n readonly text: string\n readonly words?: ReadonlyArray<WordTimestamp>\n readonly languageCode?: string\n }\n | { readonly _tag: \"speech-started\"; readonly atSeconds: number }\n | { readonly _tag: \"utterance-ended\"; readonly atSeconds: number }\n | {\n readonly _tag: \"audio-event\"\n readonly label: string\n readonly startSeconds: number\n readonly endSeconds: number\n }\n | { readonly _tag: \"metadata\"; readonly raw: unknown }\n | { readonly _tag: \"error\"; readonly code?: string; readonly message: string }\n\nexport const isPartial = (e: TranscriptEvent): e is Extract<TranscriptEvent, { _tag: \"partial\" }> =>\n e._tag === \"partial\"\nexport const isFinal = (e: TranscriptEvent): e is Extract<TranscriptEvent, { _tag: \"final\" }> =>\n e._tag === \"final\"\nexport const isSpeechStarted = (\n e: TranscriptEvent,\n): e is Extract<TranscriptEvent, { _tag: \"speech-started\" }> => e._tag === \"speech-started\"\nexport const isUtteranceEnded = (\n e: TranscriptEvent,\n): e is Extract<TranscriptEvent, { _tag: \"utterance-ended\" }> => e._tag === \"utterance-ended\"\nexport const isAudioEvent = (\n e: TranscriptEvent,\n): e is Extract<TranscriptEvent, { _tag: \"audio-event\" }> => e._tag === \"audio-event\"\nexport const isMetadata = (\n e: TranscriptEvent,\n): e is Extract<TranscriptEvent, { _tag: \"metadata\" }> => e._tag === \"metadata\"\nexport const isError = (e: TranscriptEvent): e is Extract<TranscriptEvent, { _tag: \"error\" }> =>\n e._tag === \"error\"\n"],"mappings":";;;;;;;;;;;AAiEA,MAAa,aAAa,MACxB,EAAE,SAAS;AACb,MAAa,WAAW,MACtB,EAAE,SAAS;AACb,MAAa,mBACX,MAC8D,EAAE,SAAS;AAC3E,MAAa,oBACX,MAC+D,EAAE,SAAS;AAC5E,MAAa,gBACX,MAC2D,EAAE,SAAS;AACxE,MAAa,cACX,MACwD,EAAE,SAAS;AACrE,MAAa,WAAW,MACtB,EAAE,SAAS"}
@@ -1,2 +1,2 @@
1
- import { c as functionCalls, d as textDeltas, f as toStructured, i as TurnEvent, l as isTurnComplete, n as RefusalRejected, o as appendTurn, r as Turn, s as assistantMessages, t as InteractionEvent, u as reasonings } from "../Turn-OPaILVIB.mjs";
1
+ import { c as functionCalls, d as textDeltas, f as toStructured, i as TurnEvent, l as isTurnComplete, n as RefusalRejected, o as appendTurn, r as Turn, s as assistantMessages, t as InteractionEvent, u as reasonings } from "../Turn-7geUcKsf.mjs";
2
2
  export { InteractionEvent, RefusalRejected, Turn, TurnEvent, appendTurn, assistantMessages, functionCalls, isTurnComplete, reasonings, textDeltas, toStructured };
@@ -1,4 +1,4 @@
1
- import { i as ImageSource } from "../Image-BZmKfIdq.mjs";
1
+ import { i as ImageSource } from "../Image-DxyXqzAM.mjs";
2
2
 
3
3
  //#region src/embedding-model/Embedding.d.ts
4
4
  declare namespace Embedding_d_exports {
@@ -1,4 +1,4 @@
1
- import { t as AiError } from "../AiError-CBuPHVKA.mjs";
1
+ import { t as AiError } from "../AiError-csR8Bhxx.mjs";
2
2
  import { EmbedInput, Embedding, Usage } from "./Embedding.mjs";
3
3
  import { Context, Effect } from "effect";
4
4
 
package/dist/index.d.mts CHANGED
@@ -1,13 +1,19 @@
1
- import { n as AiError_d_exports } from "./AiError-CBuPHVKA.mjs";
1
+ import { n as AiError_d_exports } from "./AiError-csR8Bhxx.mjs";
2
2
  import { a as Media_d_exports } from "./Media-D_CpcM1Z.mjs";
3
- import { o as Image_d_exports } from "./Image-BZmKfIdq.mjs";
4
- import { f as Items_d_exports } from "./Items-CB8Bo3FI.mjs";
5
- import { a as StructuredFormat_d_exports } from "./StructuredFormat-BWq5Hd1O.mjs";
6
- import { a as Turn_d_exports } from "./Turn-OPaILVIB.mjs";
3
+ import { o as Audio_d_exports } from "./Audio-BfCTGnH3.mjs";
4
+ import { o as Image_d_exports } from "./Image-DxyXqzAM.mjs";
5
+ import { f as Items_d_exports } from "./Items-Hg5AsYxl.mjs";
6
+ import { t as Music_d_exports } from "./domain/Music.mjs";
7
+ import { t as Transcript_d_exports } from "./domain/Transcript.mjs";
8
+ import { a as StructuredFormat_d_exports } from "./StructuredFormat-Cl41C56K.mjs";
9
+ import { a as Turn_d_exports } from "./Turn-7geUcKsf.mjs";
7
10
  import { t as Embedding_d_exports } from "./embedding-model/Embedding.mjs";
8
11
  import { t as EmbeddingModel_d_exports } from "./embedding-model/EmbeddingModel.mjs";
9
- import { l as Tool_d_exports } from "./Tool-DjVufH7i.mjs";
12
+ import { l as Tool_d_exports } from "./Tool-B8B5qVEy.mjs";
10
13
  import { t as LanguageModel_d_exports } from "./language-model/LanguageModel.mjs";
14
+ import { t as MusicGenerator_d_exports } from "./music-generator/MusicGenerator.mjs";
15
+ import { t as SpeechSynthesizer_d_exports } from "./speech-synthesizer/SpeechSynthesizer.mjs";
16
+ import { t as Transcriber_d_exports } from "./transcriber/Transcriber.mjs";
11
17
  import { t as Vector_d_exports } from "./math/Vector.mjs";
12
18
  import { t as Loop_d_exports } from "./loop/Loop.mjs";
13
19
  import { t as Outcome_d_exports } from "./tool/Outcome.mjs";
@@ -19,4 +25,4 @@ import { t as JSONL_d_exports } from "./streaming/JSONL.mjs";
19
25
  import { t as Lines_d_exports } from "./streaming/Lines.mjs";
20
26
  import { t as SSE_d_exports } from "./streaming/SSE.mjs";
21
27
  import { t as Metrics_d_exports } from "./observability/Metrics.mjs";
22
- export { AiError_d_exports as AiError, Embedding_d_exports as Embedding, EmbeddingModel_d_exports as EmbeddingModel, HistoryCheck_d_exports as HistoryCheck, Image_d_exports as Image, Items_d_exports as Items, JSONL_d_exports as JSONL, LanguageModel_d_exports as LanguageModel, Lines_d_exports as Lines, Loop_d_exports as Loop, Media_d_exports as Media, Metrics_d_exports as Metrics, Outcome_d_exports as Outcome, Resolvers_d_exports as Resolvers, SSE_d_exports as SSE, StructuredFormat_d_exports as StructuredFormat, Tool_d_exports as Tool, ToolEvent_d_exports as ToolEvent, Toolkit_d_exports as Toolkit, Turn_d_exports as Turn, Vector_d_exports as Vector };
28
+ export { AiError_d_exports as AiError, Audio_d_exports as Audio, Embedding_d_exports as Embedding, EmbeddingModel_d_exports as EmbeddingModel, HistoryCheck_d_exports as HistoryCheck, Image_d_exports as Image, Items_d_exports as Items, JSONL_d_exports as JSONL, LanguageModel_d_exports as LanguageModel, Lines_d_exports as Lines, Loop_d_exports as Loop, Media_d_exports as Media, Metrics_d_exports as Metrics, Music_d_exports as Music, MusicGenerator_d_exports as MusicGenerator, Outcome_d_exports as Outcome, Resolvers_d_exports as Resolvers, SSE_d_exports as SSE, SpeechSynthesizer_d_exports as SpeechSynthesizer, StructuredFormat_d_exports as StructuredFormat, Tool_d_exports as Tool, ToolEvent_d_exports as ToolEvent, Toolkit_d_exports as Toolkit, Transcriber_d_exports as Transcriber, Transcript_d_exports as Transcript, Turn_d_exports as Turn, Vector_d_exports as Vector };
package/dist/index.mjs CHANGED
@@ -1,12 +1,18 @@
1
1
  import { t as AiError_exports } from "./domain/AiError.mjs";
2
+ import { t as Audio_exports } from "./domain/Audio.mjs";
2
3
  import { t as Image_exports } from "./domain/Image.mjs";
3
4
  import { t as Items_exports } from "./domain/Items.mjs";
4
5
  import { t as Media_exports } from "./domain/Media.mjs";
6
+ import { t as Music_exports } from "./domain/Music.mjs";
7
+ import { t as Transcript_exports } from "./domain/Transcript.mjs";
5
8
  import { t as StructuredFormat_exports } from "./structured-format/StructuredFormat.mjs";
6
9
  import { t as Turn_exports } from "./domain/Turn.mjs";
7
10
  import { t as Embedding_exports } from "./embedding-model/Embedding.mjs";
8
11
  import { t as EmbeddingModel_exports } from "./embedding-model/EmbeddingModel.mjs";
9
12
  import { t as LanguageModel_exports } from "./language-model/LanguageModel.mjs";
13
+ import { t as MusicGenerator_exports } from "./music-generator/MusicGenerator.mjs";
14
+ import { t as SpeechSynthesizer_exports } from "./speech-synthesizer/SpeechSynthesizer.mjs";
15
+ import { t as Transcriber_exports } from "./transcriber/Transcriber.mjs";
10
16
  import { t as Vector_exports } from "./math/Vector.mjs";
11
17
  import { t as Loop_exports } from "./loop/Loop.mjs";
12
18
  import { t as Tool_exports } from "./tool/Tool.mjs";
@@ -19,4 +25,4 @@ import { t as JSONL_exports } from "./streaming/JSONL.mjs";
19
25
  import { t as Lines_exports } from "./streaming/Lines.mjs";
20
26
  import { t as SSE_exports } from "./streaming/SSE.mjs";
21
27
  import { t as Metrics_exports } from "./observability/Metrics.mjs";
22
- export { AiError_exports as AiError, Embedding_exports as Embedding, EmbeddingModel_exports as EmbeddingModel, HistoryCheck_exports as HistoryCheck, Image_exports as Image, Items_exports as Items, JSONL_exports as JSONL, LanguageModel_exports as LanguageModel, Lines_exports as Lines, Loop_exports as Loop, Media_exports as Media, Metrics_exports as Metrics, Outcome_exports as Outcome, Resolvers_exports as Resolvers, SSE_exports as SSE, StructuredFormat_exports as StructuredFormat, Tool_exports as Tool, ToolEvent_exports as ToolEvent, Toolkit_exports as Toolkit, Turn_exports as Turn, Vector_exports as Vector };
28
+ export { AiError_exports as AiError, Audio_exports as Audio, Embedding_exports as Embedding, EmbeddingModel_exports as EmbeddingModel, HistoryCheck_exports as HistoryCheck, Image_exports as Image, Items_exports as Items, JSONL_exports as JSONL, LanguageModel_exports as LanguageModel, Lines_exports as Lines, Loop_exports as Loop, Media_exports as Media, Metrics_exports as Metrics, Music_exports as Music, MusicGenerator_exports as MusicGenerator, Outcome_exports as Outcome, Resolvers_exports as Resolvers, SSE_exports as SSE, SpeechSynthesizer_exports as SpeechSynthesizer, StructuredFormat_exports as StructuredFormat, Tool_exports as Tool, ToolEvent_exports as ToolEvent, Toolkit_exports as Toolkit, Transcriber_exports as Transcriber, Transcript_exports as Transcript, Turn_exports as Turn, Vector_exports as Vector };
@@ -1,8 +1,8 @@
1
- import { t as AiError } from "../AiError-CBuPHVKA.mjs";
2
- import { d as Item } from "../Items-CB8Bo3FI.mjs";
3
- import { i as StructuredFormat } from "../StructuredFormat-BWq5Hd1O.mjs";
4
- import { i as TurnEvent } from "../Turn-OPaILVIB.mjs";
5
- import { o as ToolDescriptor } from "../Tool-DjVufH7i.mjs";
1
+ import { t as AiError } from "../AiError-csR8Bhxx.mjs";
2
+ import { d as Item } from "../Items-Hg5AsYxl.mjs";
3
+ import { i as StructuredFormat } from "../StructuredFormat-Cl41C56K.mjs";
4
+ import { i as TurnEvent } from "../Turn-7geUcKsf.mjs";
5
+ import { o as ToolDescriptor } from "../Tool-B8B5qVEy.mjs";
6
6
  import { Context, Stream } from "effect";
7
7
 
8
8
  //#region src/language-model/LanguageModel.d.ts
@@ -1,5 +1,5 @@
1
- import { l as IncompleteTurn } from "../AiError-CBuPHVKA.mjs";
2
- import { i as TurnEvent, r as Turn } from "../Turn-OPaILVIB.mjs";
1
+ import { l as IncompleteTurn } from "../AiError-csR8Bhxx.mjs";
2
+ import { i as TurnEvent, r as Turn } from "../Turn-7geUcKsf.mjs";
3
3
  import { Data, Effect, Stream, SubscriptionRef } from "effect";
4
4
 
5
5
  //#region src/loop/Loop.d.ts
@@ -0,0 +1,77 @@
1
+ import { t as AiError } from "../AiError-csR8Bhxx.mjs";
2
+ import { n as AudioChunk } from "../Audio-BfCTGnH3.mjs";
3
+ import { CommonGenerateMusicRequest, CommonStreamGenerateMusicRequest, MusicResult, MusicSessionInput, WeightedPrompt } from "../domain/Music.mjs";
4
+ import { Context, Effect, Stream } from "effect";
5
+
6
+ //#region src/music-generator/MusicGenerator.d.ts
7
+ declare namespace MusicGenerator_d_exports {
8
+ export { CommonGenerateMusicRequest, CommonStreamGenerateMusicRequest, MusicGenerator, MusicGeneratorService, MusicInteractiveSession, MusicResult, MusicSessionInput, WeightedPrompt, generate, streamGeneration, streamGenerationFrom };
9
+ }
10
+ type MusicGeneratorService = {
11
+ /**
12
+ * One-shot. Prompt in, full audio bytes out. Universally supported.
13
+ * Async/poll-based providers (Suno, Mureka) hide their poll loop
14
+ * inside the adapter — caller still sees a single `Effect`.
15
+ */
16
+ readonly generate: (request: CommonGenerateMusicRequest) => Effect.Effect<MusicResult, AiError>;
17
+ /**
18
+ * Prompt in, audio chunks streamed out. Providers without a native
19
+ * chunked-output endpoint (Lyria 3 sync, Mureka, MiniMax, Stable
20
+ * Audio) emulate this by calling `generate` and emitting a single
21
+ * `AudioChunk` — first-class, no `Unsupported`.
22
+ */
23
+ readonly streamGeneration: (request: CommonStreamGenerateMusicRequest) => Stream.Stream<AudioChunk, AiError>;
24
+ /**
25
+ * Bidirectional session: a `Stream` of prompt-or-config updates flows
26
+ * in, a `Stream` of audio chunks flows out. The session WS / RPC is
27
+ * acquired on first pull and released when the output stream is
28
+ * finalized via `Stream.scoped`.
29
+ *
30
+ * Gated by the `MusicInteractiveSession` capability marker on the
31
+ * top-level helper — providers without bidirectional support don't
32
+ * ship the marker, so calls fail at `Effect.provide` with a type
33
+ * error.
34
+ */
35
+ readonly streamGenerationFrom: <E, R>(input: Stream.Stream<MusicSessionInput, E, R>, request: CommonStreamGenerateMusicRequest) => Stream.Stream<AudioChunk, AiError | E, R>;
36
+ };
37
+ declare const MusicGenerator_base: Context.ServiceClass<MusicGenerator, "@betalyra/effect-uai/MusicGenerator", MusicGeneratorService>;
38
+ declare class MusicGenerator extends MusicGenerator_base {}
39
+ declare const MusicInteractiveSession_base: Context.ServiceClass<MusicInteractiveSession, "@betalyra/effect-uai/capability/MusicInteractiveSession", void>;
40
+ /**
41
+ * Capability marker — provided by provider layers whose
42
+ * `streamGenerationFrom` is wired up at the wire level. Currently only
43
+ * Lyria RealTime (via the BidiGenerateMusic WebSocket) ships it.
44
+ * Calling `streamGenerationFrom` while only a non-interactive Layer is
45
+ * in scope fails at `Effect.provide` with a type error.
46
+ *
47
+ * Phantom — the value is `void`; providers register with
48
+ * `Layer.succeed(MusicInteractiveSession, undefined)`.
49
+ */
50
+ declare class MusicInteractiveSession extends MusicInteractiveSession_base {}
51
+ /** One-shot generation. */
52
+ declare const generate: (request: CommonGenerateMusicRequest) => Effect.Effect<MusicResult, AiError, MusicGenerator>;
53
+ /** Prompt in, audio chunks out. */
54
+ declare const streamGeneration: (request: CommonStreamGenerateMusicRequest) => Stream.Stream<AudioChunk, AiError, MusicGenerator>;
55
+ /**
56
+ * Bidirectional generation. Dual-arity: pipeable (data-last) and
57
+ * direct (data-first). Requires `MusicInteractiveSession` in R —
58
+ * providers without bidirectional support are a type error at provide
59
+ * time.
60
+ *
61
+ * @example
62
+ * ```ts
63
+ * const audio = Stream.fromIterable([
64
+ * Music.promptsInput([{ text: "minimal techno", weight: 1.0 }]),
65
+ * Music.configInput({ bpm: 124 }),
66
+ * ]).pipe(
67
+ * MusicGenerator.streamGenerationFrom({ model: "lyria-realtime-001", prompts: "" }),
68
+ * )
69
+ * ```
70
+ */
71
+ declare const streamGenerationFrom: {
72
+ (request: CommonStreamGenerateMusicRequest): <E, R>(input: Stream.Stream<MusicSessionInput, E, R>) => Stream.Stream<AudioChunk, AiError | E, R | MusicGenerator | MusicInteractiveSession>;
73
+ <E, R>(input: Stream.Stream<MusicSessionInput, E, R>, request: CommonStreamGenerateMusicRequest): Stream.Stream<AudioChunk, AiError | E, R | MusicGenerator | MusicInteractiveSession>;
74
+ };
75
+ //#endregion
76
+ export { type CommonGenerateMusicRequest, type CommonStreamGenerateMusicRequest, MusicGenerator, MusicGeneratorService, MusicInteractiveSession, type MusicResult, type MusicSessionInput, type WeightedPrompt, generate, streamGeneration, streamGenerationFrom, MusicGenerator_d_exports as t };
77
+ //# sourceMappingURL=MusicGenerator.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MusicGenerator.d.mts","names":[],"sources":["../../src/music-generator/MusicGenerator.ts"],"mappings":";;;;;;;;;KAkBY,qBAAA;;;;;;WAMD,QAAA,GACP,OAAA,EAAS,0BAAA,KACN,MAAA,CAAO,MAAA,CAAO,WAAA,EAAa,OAAA;;;;;;;WAOvB,gBAAA,GACP,OAAA,EAAS,gCAAA,KACN,MAAA,CAAO,MAAA,CAAO,UAAA,EAAY,OAAA;;AAjBjC;;;;;;;;;;WA6BW,oBAAA,SACP,KAAA,EAAO,MAAA,CAAO,MAAA,CAAO,iBAAA,EAAmB,CAAA,EAAG,CAAA,GAC3C,OAAA,EAAS,gCAAA,KACN,MAAA,CAAO,MAAA,CAAO,UAAA,EAAY,OAAA,GAAkB,CAAA,EAAG,CAAA;AAAA;AAAA,cACrD,mBAAA;cAEY,cAAA,SAAuB,mBAAA;AAAA,cAEhC,4BAAA;;;;;;;;;;;cAYS,uBAAA,SAAgC,4BAAA;;cAKhC,QAAA,GACX,OAAA,EAAS,0BAAA,KACR,MAAA,CAAO,MAAA,CAAO,WAAA,EAAa,OAAA,EAAiB,cAAA;;cAIlC,gBAAA,GACX,OAAA,EAAS,gCAAA,KACR,MAAA,CAAO,MAAA,CAAO,UAAA,EAAY,OAAA,EAAiB,cAAA;;;;;;;;;;;;;;;;;cAmBjC,oBAAA;EAAA,CAET,OAAA,EAAS,gCAAA,UAET,KAAA,EAAO,MAAA,CAAO,MAAA,CAAO,iBAAA,EAAmB,CAAA,EAAG,CAAA,MACxC,MAAA,CAAO,MAAA,CAAO,UAAA,EAAY,OAAA,GAAkB,CAAA,EAAG,CAAA,GAAI,cAAA,GAAiB,uBAAA;EAAA,OAEvE,KAAA,EAAO,MAAA,CAAO,MAAA,CAAO,iBAAA,EAAmB,CAAA,EAAG,CAAA,GAC3C,OAAA,EAAS,gCAAA,GACR,MAAA,CAAO,MAAA,CAAO,UAAA,EAAY,OAAA,GAAkB,CAAA,EAAG,CAAA,GAAI,cAAA,GAAiB,uBAAA;AAAA"}
@@ -0,0 +1,51 @@
1
+ import { n as __exportAll } from "../chunk-uyGKjUfl.mjs";
2
+ import { Context, Effect, Function, Stream } from "effect";
3
+ //#region src/music-generator/MusicGenerator.ts
4
+ var MusicGenerator_exports = /* @__PURE__ */ __exportAll({
5
+ MusicGenerator: () => MusicGenerator,
6
+ MusicInteractiveSession: () => MusicInteractiveSession,
7
+ generate: () => generate,
8
+ streamGeneration: () => streamGeneration,
9
+ streamGenerationFrom: () => streamGenerationFrom
10
+ });
11
+ var MusicGenerator = class extends Context.Service()("@betalyra/effect-uai/MusicGenerator") {};
12
+ /**
13
+ * Capability marker — provided by provider layers whose
14
+ * `streamGenerationFrom` is wired up at the wire level. Currently only
15
+ * Lyria RealTime (via the BidiGenerateMusic WebSocket) ships it.
16
+ * Calling `streamGenerationFrom` while only a non-interactive Layer is
17
+ * in scope fails at `Effect.provide` with a type error.
18
+ *
19
+ * Phantom — the value is `void`; providers register with
20
+ * `Layer.succeed(MusicInteractiveSession, undefined)`.
21
+ */
22
+ var MusicInteractiveSession = class extends Context.Service()("@betalyra/effect-uai/capability/MusicInteractiveSession") {};
23
+ /** One-shot generation. */
24
+ const generate = (request) => Effect.flatMap(MusicGenerator.asEffect(), (s) => s.generate(request));
25
+ /** Prompt in, audio chunks out. */
26
+ const streamGeneration = (request) => Stream.unwrap(Effect.map(MusicGenerator.asEffect(), (s) => s.streamGeneration(request)));
27
+ /**
28
+ * Bidirectional generation. Dual-arity: pipeable (data-last) and
29
+ * direct (data-first). Requires `MusicInteractiveSession` in R —
30
+ * providers without bidirectional support are a type error at provide
31
+ * time.
32
+ *
33
+ * @example
34
+ * ```ts
35
+ * const audio = Stream.fromIterable([
36
+ * Music.promptsInput([{ text: "minimal techno", weight: 1.0 }]),
37
+ * Music.configInput({ bpm: 124 }),
38
+ * ]).pipe(
39
+ * MusicGenerator.streamGenerationFrom({ model: "lyria-realtime-001", prompts: "" }),
40
+ * )
41
+ * ```
42
+ */
43
+ const streamGenerationFrom = Function.dual(2, (input, request) => Stream.unwrap(Effect.gen(function* () {
44
+ const s = yield* MusicGenerator.asEffect();
45
+ yield* MusicInteractiveSession.asEffect();
46
+ return s.streamGenerationFrom(input, request);
47
+ })));
48
+ //#endregion
49
+ export { MusicGenerator, MusicInteractiveSession, generate, streamGeneration, streamGenerationFrom, MusicGenerator_exports as t };
50
+
51
+ //# sourceMappingURL=MusicGenerator.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MusicGenerator.mjs","names":[],"sources":["../../src/music-generator/MusicGenerator.ts"],"sourcesContent":["import { Context, Effect, Function, Stream } from \"effect\"\nimport * as AiError from \"../domain/AiError.js\"\nimport type { AudioChunk } from \"../domain/Audio.js\"\nimport type {\n CommonGenerateMusicRequest,\n CommonStreamGenerateMusicRequest,\n MusicResult,\n MusicSessionInput,\n} from \"../domain/Music.js\"\n\nexport type {\n CommonGenerateMusicRequest,\n CommonStreamGenerateMusicRequest,\n MusicResult,\n MusicSessionInput,\n WeightedPrompt,\n} from \"../domain/Music.js\"\n\nexport type MusicGeneratorService = {\n /**\n * One-shot. Prompt in, full audio bytes out. Universally supported.\n * Async/poll-based providers (Suno, Mureka) hide their poll loop\n * inside the adapter — caller still sees a single `Effect`.\n */\n readonly generate: (\n request: CommonGenerateMusicRequest,\n ) => Effect.Effect<MusicResult, AiError.AiError>\n /**\n * Prompt in, audio chunks streamed out. Providers without a native\n * chunked-output endpoint (Lyria 3 sync, Mureka, MiniMax, Stable\n * Audio) emulate this by calling `generate` and emitting a single\n * `AudioChunk` — first-class, no `Unsupported`.\n */\n readonly streamGeneration: (\n request: CommonStreamGenerateMusicRequest,\n ) => Stream.Stream<AudioChunk, AiError.AiError>\n /**\n * Bidirectional session: a `Stream` of prompt-or-config updates flows\n * in, a `Stream` of audio chunks flows out. The session WS / RPC is\n * acquired on first pull and released when the output stream is\n * finalized via `Stream.scoped`.\n *\n * Gated by the `MusicInteractiveSession` capability marker on the\n * top-level helper — providers without bidirectional support don't\n * ship the marker, so calls fail at `Effect.provide` with a type\n * error.\n */\n readonly streamGenerationFrom: <E, R>(\n input: Stream.Stream<MusicSessionInput, E, R>,\n request: CommonStreamGenerateMusicRequest,\n ) => Stream.Stream<AudioChunk, AiError.AiError | E, R>\n}\n\nexport class MusicGenerator extends Context.Service<MusicGenerator, MusicGeneratorService>()(\n \"@betalyra/effect-uai/MusicGenerator\",\n) {}\n\n/**\n * Capability marker — provided by provider layers whose\n * `streamGenerationFrom` is wired up at the wire level. Currently only\n * Lyria RealTime (via the BidiGenerateMusic WebSocket) ships it.\n * Calling `streamGenerationFrom` while only a non-interactive Layer is\n * in scope fails at `Effect.provide` with a type error.\n *\n * Phantom — the value is `void`; providers register with\n * `Layer.succeed(MusicInteractiveSession, undefined)`.\n */\nexport class MusicInteractiveSession extends Context.Service<MusicInteractiveSession, void>()(\n \"@betalyra/effect-uai/capability/MusicInteractiveSession\",\n) {}\n\n/** One-shot generation. */\nexport const generate = (\n request: CommonGenerateMusicRequest,\n): Effect.Effect<MusicResult, AiError.AiError, MusicGenerator> =>\n Effect.flatMap(MusicGenerator.asEffect(), (s) => s.generate(request))\n\n/** Prompt in, audio chunks out. */\nexport const streamGeneration = (\n request: CommonStreamGenerateMusicRequest,\n): Stream.Stream<AudioChunk, AiError.AiError, MusicGenerator> =>\n Stream.unwrap(Effect.map(MusicGenerator.asEffect(), (s) => s.streamGeneration(request)))\n\n/**\n * Bidirectional generation. Dual-arity: pipeable (data-last) and\n * direct (data-first). Requires `MusicInteractiveSession` in R —\n * providers without bidirectional support are a type error at provide\n * time.\n *\n * @example\n * ```ts\n * const audio = Stream.fromIterable([\n * Music.promptsInput([{ text: \"minimal techno\", weight: 1.0 }]),\n * Music.configInput({ bpm: 124 }),\n * ]).pipe(\n * MusicGenerator.streamGenerationFrom({ model: \"lyria-realtime-001\", prompts: \"\" }),\n * )\n * ```\n */\nexport const streamGenerationFrom: {\n (\n request: CommonStreamGenerateMusicRequest,\n ): <E, R>(\n input: Stream.Stream<MusicSessionInput, E, R>,\n ) => Stream.Stream<AudioChunk, AiError.AiError | E, R | MusicGenerator | MusicInteractiveSession>\n <E, R>(\n input: Stream.Stream<MusicSessionInput, E, R>,\n request: CommonStreamGenerateMusicRequest,\n ): Stream.Stream<AudioChunk, AiError.AiError | E, R | MusicGenerator | MusicInteractiveSession>\n} = Function.dual(\n 2,\n <E, R>(\n input: Stream.Stream<MusicSessionInput, E, R>,\n request: CommonStreamGenerateMusicRequest,\n ) =>\n Stream.unwrap(\n Effect.gen(function* () {\n const s = yield* MusicGenerator.asEffect()\n yield* MusicInteractiveSession.asEffect()\n return s.streamGenerationFrom(input, request)\n }),\n ),\n)\n"],"mappings":";;;;;;;;;;AAqDA,IAAa,iBAAb,cAAoC,QAAQ,SAAgD,CAC1F,sCACD,CAAC;;;;;;;;;;;AAYF,IAAa,0BAAb,cAA6C,QAAQ,SAAwC,CAC3F,0DACD,CAAC;;AAGF,MAAa,YACX,YAEA,OAAO,QAAQ,eAAe,UAAU,GAAG,MAAM,EAAE,SAAS,QAAQ,CAAC;;AAGvE,MAAa,oBACX,YAEA,OAAO,OAAO,OAAO,IAAI,eAAe,UAAU,GAAG,MAAM,EAAE,iBAAiB,QAAQ,CAAC,CAAC;;;;;;;;;;;;;;;;;AAkB1F,MAAa,uBAUT,SAAS,KACX,IAEE,OACA,YAEA,OAAO,OACL,OAAO,IAAI,aAAa;CACtB,MAAM,IAAI,OAAO,eAAe,UAAU;AAC1C,QAAO,wBAAwB,UAAU;AACzC,QAAO,EAAE,qBAAqB,OAAO,QAAQ;EAC7C,CACH,CACJ"}
@@ -0,0 +1 @@
1
+ export { };
@@ -0,0 +1,154 @@
1
+ import { configInput, promptsInput } from "../domain/Music.mjs";
2
+ import { generate, streamGeneration, streamGenerationFrom } from "./MusicGenerator.mjs";
3
+ import { i as it, n as globalExpect, r as describe, t as import_dist } from "../dist-DV5ISja1.mjs";
4
+ import { layer, layerWithoutInteractive } from "../testing/MockMusicGenerator.mjs";
5
+ import { Effect, Stream } from "effect";
6
+ //#region src/music-generator/MusicGenerator.test.ts
7
+ const result = {
8
+ format: {
9
+ container: "mp3",
10
+ encoding: "mp3",
11
+ sampleRate: 44100,
12
+ channels: 2
13
+ },
14
+ bytes: new Uint8Array([
15
+ 255,
16
+ 251,
17
+ 144,
18
+ 0
19
+ ]),
20
+ durationSeconds: 30,
21
+ lyrics: "[Verse]\nhello\n",
22
+ watermark: { kind: "synthid" }
23
+ };
24
+ const chunk = (n) => ({ bytes: new Uint8Array([n]) });
25
+ describe("MusicGenerator.generate", () => {
26
+ it("returns the scripted MusicResult", async () => {
27
+ const mock = layer({ results: [result] });
28
+ const program = generate({
29
+ model: "mock-music",
30
+ prompts: "upbeat indie pop"
31
+ });
32
+ const out = await Effect.runPromise(program.pipe(Effect.provide(mock.layer)));
33
+ globalExpect(out.bytes).toEqual(result.bytes);
34
+ globalExpect(out.durationSeconds).toBe(30);
35
+ globalExpect(out.watermark?.kind).toBe("synthid");
36
+ globalExpect(out.lyrics).toContain("[Verse]");
37
+ });
38
+ it("records the request shape on the recorder", async () => {
39
+ const mock = layer({ results: [result, result] });
40
+ const program = Effect.gen(function* () {
41
+ yield* generate({
42
+ model: "m",
43
+ prompts: "techno"
44
+ });
45
+ yield* generate({
46
+ model: "m",
47
+ prompts: [{
48
+ text: "synthwave",
49
+ weight: 1
50
+ }, {
51
+ text: "80s movie OST",
52
+ weight: .4
53
+ }],
54
+ bpm: 120,
55
+ instrumental: true
56
+ });
57
+ return yield* mock.recorder;
58
+ });
59
+ const rec = await Effect.runPromise(program.pipe(Effect.provide(mock.layer)));
60
+ globalExpect(rec.generateCalls.length).toBe(2);
61
+ globalExpect(rec.generateCalls[1].bpm).toBe(120);
62
+ globalExpect(rec.generateCalls[1].instrumental).toBe(true);
63
+ globalExpect(Array.isArray(rec.generateCalls[1].prompts)).toBe(true);
64
+ });
65
+ });
66
+ describe("MusicGenerator.streamGeneration", () => {
67
+ it("emits scripted chunks", async () => {
68
+ const mock = layer({ streamGenerationChunks: [[
69
+ chunk(1),
70
+ chunk(2),
71
+ chunk(3)
72
+ ]] });
73
+ const program = Stream.runCollect(streamGeneration({
74
+ model: "m",
75
+ prompts: "ambient"
76
+ }));
77
+ globalExpect((await Effect.runPromise(program.pipe(Effect.provide(mock.layer)))).map((c) => Array.from(c.bytes))).toEqual([
78
+ [1],
79
+ [2],
80
+ [3]
81
+ ]);
82
+ });
83
+ });
84
+ describe("MusicGenerator capability marker (compile-time)", () => {
85
+ const sgfReq = {
86
+ model: "m",
87
+ prompts: ""
88
+ };
89
+ it("requires `MusicInteractiveSession` on the R channel of streamGenerationFrom", () => {
90
+ (0, import_dist.expectTypeOf)(Stream.fromIterable([promptsInput([{ text: "techno" }])]).pipe(streamGenerationFrom(sgfReq))).toEqualTypeOf();
91
+ });
92
+ it("does NOT require `MusicInteractiveSession` for sync `generate`", () => {
93
+ (0, import_dist.expectTypeOf)(generate({
94
+ model: "m",
95
+ prompts: "ambient"
96
+ })).toEqualTypeOf();
97
+ });
98
+ it("does NOT require `MusicInteractiveSession` for `streamGeneration`", () => {
99
+ (0, import_dist.expectTypeOf)(streamGeneration({
100
+ model: "m",
101
+ prompts: "ambient"
102
+ })).toEqualTypeOf();
103
+ });
104
+ it("a layer without the marker leaves `MusicInteractiveSession` unsatisfied in R", () => {
105
+ const noMarker = layerWithoutInteractive({});
106
+ const audio = Stream.fromIterable([promptsInput([{ text: "techno" }])]).pipe(streamGenerationFrom(sgfReq));
107
+ (0, import_dist.expectTypeOf)(Stream.runDrain(audio).pipe(Effect.provide(noMarker.layer))).toEqualTypeOf();
108
+ });
109
+ it("a full layer (with marker) clears R to never", () => {
110
+ const fullMock = layer({ streamGenerationFromChunks: [[]] });
111
+ const audio = Stream.fromIterable([promptsInput([{ text: "techno" }])]).pipe(streamGenerationFrom(sgfReq));
112
+ (0, import_dist.expectTypeOf)(Stream.runDrain(audio).pipe(Effect.provide(fullMock.layer))).toEqualTypeOf();
113
+ });
114
+ });
115
+ describe("MusicGenerator.streamGenerationFrom", () => {
116
+ const sgfReq = {
117
+ model: "lyria-realtime-001",
118
+ prompts: ""
119
+ };
120
+ it("drains a session-input stream and emits scripted audio", async () => {
121
+ const mock = layer({ streamGenerationFromChunks: [[chunk(10), chunk(20)]] });
122
+ const audio = Stream.fromIterable([
123
+ promptsInput([{
124
+ text: "minimal techno",
125
+ weight: 1
126
+ }]),
127
+ configInput({ bpm: 124 }),
128
+ promptsInput([{
129
+ text: "minimal techno",
130
+ weight: 1
131
+ }, {
132
+ text: "1980s synthwave",
133
+ weight: .3
134
+ }])
135
+ ]).pipe(streamGenerationFrom(sgfReq));
136
+ globalExpect((await Effect.runPromise(Stream.runCollect(audio).pipe(Effect.provide(mock.layer)))).map((c) => Array.from(c.bytes))).toEqual([[10], [20]]);
137
+ });
138
+ it("records the request on the streamGenerationFrom call channel", async () => {
139
+ const mock = layer({ streamGenerationFromChunks: [[chunk(42)]] });
140
+ const program = Effect.gen(function* () {
141
+ yield* Stream.runDrain(Stream.fromIterable([promptsInput([{ text: "x" }])]).pipe(streamGenerationFrom(sgfReq)));
142
+ return yield* mock.recorder;
143
+ });
144
+ const rec = await Effect.runPromise(program.pipe(Effect.provide(mock.layer)));
145
+ globalExpect(rec.streamGenerationFromCalls.length).toBe(1);
146
+ globalExpect(rec.streamGenerationFromCalls[0].model).toBe("lyria-realtime-001");
147
+ globalExpect(rec.generateCalls.length).toBe(0);
148
+ globalExpect(rec.streamGenerationCalls.length).toBe(0);
149
+ });
150
+ });
151
+ //#endregion
152
+ export {};
153
+
154
+ //# sourceMappingURL=MusicGenerator.test.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MusicGenerator.test.mjs","names":["MockMusicGenerator.layer","MusicGenerator.generate","MusicGenerator.streamGeneration","MusicGenerator.streamGenerationFrom","MockMusicGenerator.layerWithoutInteractive"],"sources":["../../src/music-generator/MusicGenerator.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 { AudioChunk, AudioFormat } from \"../domain/Audio.js\"\nimport { configInput, promptsInput, type MusicResult } from \"../domain/Music.js\"\nimport * as MockMusicGenerator from \"../testing/MockMusicGenerator.js\"\nimport * as MusicGenerator from \"./MusicGenerator.js\"\n\nconst mp3Format: AudioFormat = {\n container: \"mp3\",\n encoding: \"mp3\",\n sampleRate: 44100,\n channels: 2,\n}\n\nconst result: MusicResult = {\n format: mp3Format,\n bytes: new Uint8Array([0xff, 0xfb, 0x90, 0x00]),\n durationSeconds: 30,\n lyrics: \"[Verse]\\nhello\\n\",\n watermark: { kind: \"synthid\" },\n}\n\nconst chunk = (n: number): AudioChunk => ({ bytes: new Uint8Array([n]) })\n\ndescribe(\"MusicGenerator.generate\", () => {\n it(\"returns the scripted MusicResult\", async () => {\n const mock = MockMusicGenerator.layer({ results: [result] })\n const program = MusicGenerator.generate({\n model: \"mock-music\",\n prompts: \"upbeat indie pop\",\n })\n const out = await Effect.runPromise(program.pipe(Effect.provide(mock.layer)))\n expect(out.bytes).toEqual(result.bytes)\n expect(out.durationSeconds).toBe(30)\n expect(out.watermark?.kind).toBe(\"synthid\")\n expect(out.lyrics).toContain(\"[Verse]\")\n })\n\n it(\"records the request shape on the recorder\", async () => {\n const mock = MockMusicGenerator.layer({ results: [result, result] })\n const program = Effect.gen(function* () {\n yield* MusicGenerator.generate({ model: \"m\", prompts: \"techno\" })\n yield* MusicGenerator.generate({\n model: \"m\",\n prompts: [\n { text: \"synthwave\", weight: 1.0 },\n { text: \"80s movie OST\", weight: 0.4 },\n ],\n bpm: 120,\n instrumental: true,\n })\n return yield* mock.recorder\n })\n const rec = await Effect.runPromise(program.pipe(Effect.provide(mock.layer)))\n expect(rec.generateCalls.length).toBe(2)\n expect(rec.generateCalls[1]!.bpm).toBe(120)\n expect(rec.generateCalls[1]!.instrumental).toBe(true)\n expect(Array.isArray(rec.generateCalls[1]!.prompts)).toBe(true)\n })\n})\n\ndescribe(\"MusicGenerator.streamGeneration\", () => {\n it(\"emits scripted chunks\", async () => {\n const mock = MockMusicGenerator.layer({\n streamGenerationChunks: [[chunk(1), chunk(2), chunk(3)]],\n })\n const program = Stream.runCollect(\n MusicGenerator.streamGeneration({ model: \"m\", prompts: \"ambient\" }),\n )\n const out = await Effect.runPromise(program.pipe(Effect.provide(mock.layer)))\n expect(out.map((c) => Array.from(c.bytes))).toEqual([[1], [2], [3]])\n })\n})\n\ndescribe(\"MusicGenerator capability marker (compile-time)\", () => {\n const sgfReq: MusicGenerator.CommonStreamGenerateMusicRequest = {\n model: \"m\",\n prompts: \"\",\n }\n\n it(\"requires `MusicInteractiveSession` on the R channel of streamGenerationFrom\", () => {\n const inputs = Stream.fromIterable([promptsInput([{ text: \"techno\" }])])\n const audio = inputs.pipe(MusicGenerator.streamGenerationFrom(sgfReq))\n expectTypeOf(audio).toEqualTypeOf<\n Stream.Stream<\n AudioChunk,\n AiError.AiError,\n MusicGenerator.MusicGenerator | MusicGenerator.MusicInteractiveSession\n >\n >()\n })\n\n it(\"does NOT require `MusicInteractiveSession` for sync `generate`\", () => {\n const eff = MusicGenerator.generate({ model: \"m\", prompts: \"ambient\" })\n expectTypeOf(eff).toEqualTypeOf<\n Effect.Effect<MusicResult, AiError.AiError, MusicGenerator.MusicGenerator>\n >()\n })\n\n it(\"does NOT require `MusicInteractiveSession` for `streamGeneration`\", () => {\n const audio = MusicGenerator.streamGeneration({ model: \"m\", prompts: \"ambient\" })\n expectTypeOf(audio).toEqualTypeOf<\n Stream.Stream<AudioChunk, AiError.AiError, MusicGenerator.MusicGenerator>\n >()\n })\n\n it(\"a layer without the marker leaves `MusicInteractiveSession` unsatisfied in R\", () => {\n const noMarker = MockMusicGenerator.layerWithoutInteractive({})\n const inputs = Stream.fromIterable([promptsInput([{ text: \"techno\" }])])\n const audio = inputs.pipe(MusicGenerator.streamGenerationFrom(sgfReq))\n const program = Stream.runDrain(audio).pipe(Effect.provide(noMarker.layer))\n expectTypeOf(program).toEqualTypeOf<\n Effect.Effect<void, AiError.AiError, MusicGenerator.MusicInteractiveSession>\n >()\n })\n\n it(\"a full layer (with marker) clears R to never\", () => {\n const fullMock = MockMusicGenerator.layer({\n streamGenerationFromChunks: [[]],\n })\n const inputs = Stream.fromIterable([promptsInput([{ text: \"techno\" }])])\n const audio = inputs.pipe(MusicGenerator.streamGenerationFrom(sgfReq))\n const program = Stream.runDrain(audio).pipe(Effect.provide(fullMock.layer))\n expectTypeOf(program).toEqualTypeOf<Effect.Effect<void, AiError.AiError, never>>()\n })\n})\n\ndescribe(\"MusicGenerator.streamGenerationFrom\", () => {\n const sgfReq: MusicGenerator.CommonStreamGenerateMusicRequest = {\n model: \"lyria-realtime-001\",\n prompts: \"\",\n }\n\n it(\"drains a session-input stream and emits scripted audio\", async () => {\n const mock = MockMusicGenerator.layer({\n streamGenerationFromChunks: [[chunk(10), chunk(20)]],\n })\n const inputs = Stream.fromIterable([\n promptsInput([{ text: \"minimal techno\", weight: 1.0 }]),\n configInput({ bpm: 124 }),\n promptsInput([\n { text: \"minimal techno\", weight: 1.0 },\n { text: \"1980s synthwave\", weight: 0.3 },\n ]),\n ])\n const audio = inputs.pipe(MusicGenerator.streamGenerationFrom(sgfReq))\n const out = await Effect.runPromise(Stream.runCollect(audio).pipe(Effect.provide(mock.layer)))\n expect(out.map((c) => Array.from(c.bytes))).toEqual([[10], [20]])\n })\n\n it(\"records the request on the streamGenerationFrom call channel\", async () => {\n const mock = MockMusicGenerator.layer({\n streamGenerationFromChunks: [[chunk(42)]],\n })\n const program = Effect.gen(function* () {\n yield* Stream.runDrain(\n Stream.fromIterable([promptsInput([{ text: \"x\" }])]).pipe(\n MusicGenerator.streamGenerationFrom(sgfReq),\n ),\n )\n return yield* mock.recorder\n })\n const rec = await Effect.runPromise(program.pipe(Effect.provide(mock.layer)))\n expect(rec.streamGenerationFromCalls.length).toBe(1)\n expect(rec.streamGenerationFromCalls[0]!.model).toBe(\"lyria-realtime-001\")\n expect(rec.generateCalls.length).toBe(0)\n expect(rec.streamGenerationCalls.length).toBe(0)\n })\n})\n"],"mappings":"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"}