@effect-uai/core 0.6.0 → 0.7.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 (78) hide show
  1. package/README.md +1 -1
  2. package/dist/{Audio-BfCTGnH3.d.mts → Audio-DPlTsNdz.d.mts} +3 -2
  3. package/dist/Audio-DPlTsNdz.d.mts.map +1 -0
  4. package/dist/{Items-pXR5BAgW.d.mts → Items-D8UaXQx_.d.mts} +4 -4
  5. package/dist/{Items-pXR5BAgW.d.mts.map → Items-D8UaXQx_.d.mts.map} +1 -1
  6. package/dist/{Tool-DP-AwKOf.d.mts → Tool-CiFXYjmR.d.mts} +2 -2
  7. package/dist/{Tool-DP-AwKOf.d.mts.map → Tool-CiFXYjmR.d.mts.map} +1 -1
  8. package/dist/capabilities/Capabilities.d.mts +78 -0
  9. package/dist/capabilities/Capabilities.d.mts.map +1 -0
  10. package/dist/capabilities/Capabilities.mjs +65 -0
  11. package/dist/capabilities/Capabilities.mjs.map +1 -0
  12. package/dist/domain/Audio.d.mts +1 -1
  13. package/dist/domain/Audio.mjs.map +1 -1
  14. package/dist/domain/Items.d.mts +1 -1
  15. package/dist/domain/Music.d.mts +131 -72
  16. package/dist/domain/Music.d.mts.map +1 -1
  17. package/dist/domain/Music.mjs +36 -9
  18. package/dist/domain/Music.mjs.map +1 -1
  19. package/dist/domain/Transcript.d.mts +8 -2
  20. package/dist/domain/Transcript.d.mts.map +1 -1
  21. package/dist/domain/Transcript.mjs.map +1 -1
  22. package/dist/domain/Turn.d.mts +1 -1
  23. package/dist/embedding-model/Embedding.d.mts +12 -2
  24. package/dist/embedding-model/Embedding.d.mts.map +1 -1
  25. package/dist/embedding-model/Embedding.mjs.map +1 -1
  26. package/dist/embedding-model/EmbeddingModel.d.mts +36 -23
  27. package/dist/embedding-model/EmbeddingModel.d.mts.map +1 -1
  28. package/dist/embedding-model/EmbeddingModel.mjs +20 -1
  29. package/dist/embedding-model/EmbeddingModel.mjs.map +1 -1
  30. package/dist/embedding-model/EmbeddingModel.test.mjs +15 -3
  31. package/dist/embedding-model/EmbeddingModel.test.mjs.map +1 -1
  32. package/dist/index.d.mts +5 -4
  33. package/dist/index.mjs +2 -1
  34. package/dist/language-model/LanguageModel.d.mts +2 -2
  35. package/dist/music-generator/MusicGenerator.d.mts +48 -25
  36. package/dist/music-generator/MusicGenerator.d.mts.map +1 -1
  37. package/dist/music-generator/MusicGenerator.mjs +17 -9
  38. package/dist/music-generator/MusicGenerator.mjs.map +1 -1
  39. package/dist/music-generator/MusicGenerator.test.mjs +81 -56
  40. package/dist/music-generator/MusicGenerator.test.mjs.map +1 -1
  41. package/dist/speech-synthesizer/SpeechSynthesizer.d.mts +21 -36
  42. package/dist/speech-synthesizer/SpeechSynthesizer.d.mts.map +1 -1
  43. package/dist/speech-synthesizer/SpeechSynthesizer.mjs.map +1 -1
  44. package/dist/speech-synthesizer/SpeechSynthesizer.test.mjs +3 -3
  45. package/dist/speech-synthesizer/SpeechSynthesizer.test.mjs.map +1 -1
  46. package/dist/testing/MockMusicGenerator.d.mts +12 -7
  47. package/dist/testing/MockMusicGenerator.d.mts.map +1 -1
  48. package/dist/testing/MockMusicGenerator.mjs +4 -3
  49. package/dist/testing/MockMusicGenerator.mjs.map +1 -1
  50. package/dist/testing/MockProvider.d.mts +1 -1
  51. package/dist/testing/MockSpeechSynthesizer.d.mts +1 -1
  52. package/dist/tool/Approval.d.mts +1 -1
  53. package/dist/tool/HistoryCheck.d.mts +1 -1
  54. package/dist/tool/Tool.d.mts +1 -1
  55. package/dist/tool/ToolResult.d.mts +1 -1
  56. package/dist/tool/Toolkit.d.mts +2 -2
  57. package/dist/transcriber/Transcriber.d.mts +11 -10
  58. package/dist/transcriber/Transcriber.d.mts.map +1 -1
  59. package/dist/transcriber/Transcriber.mjs.map +1 -1
  60. package/dist/transcriber/Transcriber.test.mjs +3 -3
  61. package/dist/transcriber/Transcriber.test.mjs.map +1 -1
  62. package/package.json +5 -1
  63. package/src/capabilities/Capabilities.ts +81 -0
  64. package/src/domain/Audio.ts +2 -1
  65. package/src/domain/Music.ts +142 -68
  66. package/src/domain/Transcript.ts +7 -1
  67. package/src/embedding-model/Embedding.ts +11 -0
  68. package/src/embedding-model/EmbeddingModel.test.ts +15 -4
  69. package/src/embedding-model/EmbeddingModel.ts +48 -21
  70. package/src/index.ts +1 -0
  71. package/src/music-generator/MusicGenerator.test.ts +78 -53
  72. package/src/music-generator/MusicGenerator.ts +65 -24
  73. package/src/speech-synthesizer/SpeechSynthesizer.test.ts +3 -3
  74. package/src/speech-synthesizer/SpeechSynthesizer.ts +18 -33
  75. package/src/testing/MockMusicGenerator.ts +28 -18
  76. package/src/transcriber/Transcriber.test.ts +3 -3
  77. package/src/transcriber/Transcriber.ts +10 -7
  78. package/dist/Audio-BfCTGnH3.d.mts.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"Music.mjs","names":[],"sources":["../../src/domain/Music.ts"],"sourcesContent":["import type { AudioBlob, AudioFormat } from \"./Audio.js\"\n\n/**\n * Prompt fragment with a relative weight. Native to Lyria RealTime\n * (`{ text, weight }` pairs blended in the model). Single-prompt\n * providers (Suno, Mureka, MiniMax) flatten to text at the adapter\n * layer.\n */\nexport type WeightedPrompt = {\n readonly text: string\n /** Default `1.0`. Range typically `[0, 1]`; provider-dependent. */\n readonly weight?: number\n}\n\n/**\n * Cross-provider music-generation request. Provider-specific extras\n * (Lyria `mode`, ElevenLabs `composition_plan`, Suno custom-mode `title`,\n * MiniMax `lyrics_optimizer`) live on each provider's typed request\n * which extends this and narrows `model`.\n */\nexport type CommonGenerateMusicRequest = {\n /** Model identifier. Each provider narrows. */\n readonly model: string\n /** Single prompt string or weighted-prompt list (blended where supported). */\n readonly prompts: string | ReadonlyArray<WeightedPrompt>\n /**\n * Lyrics text, optionally with section tags like `[Verse]` / `[Chorus]` /\n * `[Bridge]` / `[Outro]`. Ignored for instrumental-only providers or\n * when `instrumental: true`.\n */\n readonly lyrics?: string\n /** Target duration in seconds. Provider may treat as a hint or hard limit. */\n readonly durationSeconds?: number\n /** Beats per minute (60–200 typical). */\n readonly bpm?: number\n /**\n * Musical key/mode hint. Provider-specific vocabulary (e.g. Lyria\n * RealTime uses enum values like `\"C_MAJOR\"`, `\"A_MINOR\"`).\n */\n readonly scale?: string\n /** Skip vocals / lyrics. */\n readonly instrumental?: boolean\n /** Preferred output format. Provider may override. */\n readonly outputFormat?: AudioFormat\n}\n\n/**\n * Streamed-output request. Same shape as the sync request — the\n * streaming variant only differs in how the response is delivered.\n */\nexport type CommonStreamGenerateMusicRequest = CommonGenerateMusicRequest\n\n/**\n * Bidirectional-session input. The user pushes one of these per\n * change: a new prompt blend, a config delta, or a playback control.\n * Lyria RealTime is the only provider currently surfacing these.\n */\nexport type MusicSessionInput =\n | { readonly _tag: \"prompts\"; readonly prompts: ReadonlyArray<WeightedPrompt> }\n | {\n readonly _tag: \"config\"\n readonly config: {\n readonly bpm?: number\n readonly scale?: string\n readonly density?: number\n readonly brightness?: number\n readonly guidance?: number\n readonly temperature?: number\n readonly topK?: number\n readonly seed?: number\n readonly muteBass?: boolean\n readonly muteDrums?: boolean\n readonly onlyBassAndDrums?: boolean\n }\n }\n | { readonly _tag: \"control\"; readonly action: \"play\" | \"pause\" | \"stop\" | \"reset_context\" }\n\nexport const promptsInput = (prompts: ReadonlyArray<WeightedPrompt>): MusicSessionInput => ({\n _tag: \"prompts\",\n prompts,\n})\n\nexport const configInput = (\n config: (MusicSessionInput & { _tag: \"config\" })[\"config\"],\n): MusicSessionInput => ({ _tag: \"config\", config })\n\nexport const controlInput = (\n action: (MusicSessionInput & { _tag: \"control\" })[\"action\"],\n): MusicSessionInput => ({ _tag: \"control\", action })\n\n/**\n * Sync-generation result. Extends `AudioBlob` with provider-side\n * metadata that's common across music providers:\n *\n * - `songId` — Suno task id, ElevenLabs `song_id`, etc. Used for\n * back-reference (re-download, stem export, follow-up edits).\n * - `lyrics` — generated lyrics when the model returned them (Lyria\n * text part, Mureka, Suno).\n * - `sections` — structured section markers (Lyria optional JSON\n * structure response).\n * - `watermark` — presence marker (Lyria SynthID is always set).\n */\nexport type MusicResult = AudioBlob & {\n readonly songId?: string\n readonly lyrics?: string\n readonly sections?: ReadonlyArray<{\n readonly label: string\n readonly startSeconds: number\n readonly endSeconds: number\n }>\n readonly watermark?: { readonly kind: string }\n}\n\nexport const isPromptsInput = (\n i: MusicSessionInput,\n): i is MusicSessionInput & { _tag: \"prompts\" } => i._tag === \"prompts\"\nexport const isConfigInput = (i: MusicSessionInput): i is MusicSessionInput & { _tag: \"config\" } =>\n i._tag === \"config\"\nexport const isControlInput = (\n i: MusicSessionInput,\n): i is MusicSessionInput & { _tag: \"control\" } => i._tag === \"control\"\n"],"mappings":";;;;;;;;;;AA6EA,MAAa,gBAAgB,aAA+D;CAC1F,MAAM;CACN;CACD;AAED,MAAa,eACX,YACuB;CAAE,MAAM;CAAU;CAAQ;AAEnD,MAAa,gBACX,YACuB;CAAE,MAAM;CAAW;CAAQ;AAyBpD,MAAa,kBACX,MACiD,EAAE,SAAS;AAC9D,MAAa,iBAAiB,MAC5B,EAAE,SAAS;AACb,MAAa,kBACX,MACiD,EAAE,SAAS"}
1
+ {"version":3,"file":"Music.mjs","names":[],"sources":["../../src/domain/Music.ts"],"sourcesContent":["import type { Duration } from \"effect\"\nimport type { AudioBlob, AudioChunk, AudioFormat } from \"./Audio.js\"\n\n/**\n * Prompt fragment with a relative weight. Native to Lyria RealTime\n * (`{ text, weight }` pairs blended in the model) and Riffusion compose.\n * Single-prompt providers (the majority) treat a 1-element array with\n * `weight: 1` as a plain prompt.\n */\nexport type WeightedPrompt = {\n readonly text: string\n /** Default `1.0`. Range typically `[0, 1]`; provider-dependent. */\n readonly weight?: number\n}\n\n/**\n * Cross-provider music-generation request. Trimmed to fields the\n * majority of music providers honor structurally; provider-specific\n * extras (Lyria `bpm` / `scale`, ElevenLabs `compositionPlan` /\n * `signWithC2pa`, Suno `style` / `personaId`, MiniMax `lyricsOptimizer`,\n * `instrumental` on providers that ship a wire toggle) live on each\n * provider's typed request which extends this and narrows `model`.\n *\n * Music providers are one-shot text-to-audio, not conversational. No\n * `messages[]` shape applies.\n */\nexport type CommonGenerateMusicRequest = {\n /** Model identifier. Each provider narrows. */\n readonly model: string\n /** Single prompt string. Weighted blends are provider-typed extras. */\n readonly prompt: string\n /**\n * Lyrics text, optionally with section tags like `[Verse]` /\n * `[Chorus]` / `[Bridge]` / `[Outro]`. Routed to a structured wire\n * field on providers that have one (ElevenLabs `lines`, MiniMax\n * `lyrics`, Mureka `lyrics`, Suno custom-mode `prompt`); embedded in\n * the prompt with a warning on providers without one (Lyria 3,\n * Riffusion).\n */\n readonly lyrics?: string\n /** Target duration. Provider may treat as a hint or hard limit. */\n readonly duration?: Duration.Duration\n /**\n * Reproducibility seed. Tuning hint (bucket 3): honored where the\n * provider takes one (Lyria 2 Vertex, Lyria RealTime, ElevenLabs\n * with `compositionPlan`, Stable Audio, MusicGen); silently ignored\n * elsewhere.\n */\n readonly seed?: number\n /** Preferred output format. Provider may override. */\n readonly outputFormat?: AudioFormat\n}\n\n/**\n * Streamed-output request. Same shape as the sync request: the\n * streaming variant only differs in how the response is delivered.\n */\nexport type CommonStreamGenerateMusicRequest = CommonGenerateMusicRequest\n\n/**\n * Playback-control vocabulary that converges across interactive-media\n * protocols (Web Audio, MIDI sequencer control, music SDK surfaces).\n * Provider-specific control actions (Lyria's `reset_context` and any\n * future provider's extras) live on the provider-typed session-input\n * union.\n */\nexport type MusicSessionControl = \"play\" | \"pause\" | \"stop\" | \"reset\"\n\n/**\n * Bidirectional-session input on the cross-provider surface. Two\n * load-bearing actions every interactive music session needs:\n *\n * - `prompts` — steer the active generation with a (single or\n * weighted) prompt blend.\n * - `control` — play / pause / stop / reset.\n *\n * Provider-typed services extend this union with their own `config`\n * variant for model-specific knobs (Lyria RealTime exposes density /\n * brightness / mute-stems / BPM / scale / etc. via its own\n * `LyriaRealtimeSessionInput`).\n */\nexport type MusicSessionInput =\n | { readonly _tag: \"prompts\"; readonly prompts: ReadonlyArray<WeightedPrompt> }\n | { readonly _tag: \"control\"; readonly action: MusicSessionControl }\n\nexport const promptsInput = (prompts: ReadonlyArray<WeightedPrompt>): MusicSessionInput => ({\n _tag: \"prompts\",\n prompts,\n})\n\nexport const controlInput = (action: MusicSessionControl): MusicSessionInput => ({\n _tag: \"control\",\n action,\n})\n\n/**\n * Watermark kind on the response. SynthID is mandatory on Lyria; C2PA\n * is opt-in on ElevenLabs. No provider exposes additional metadata\n * about the watermark itself, so a bare literal-union is enough.\n */\nexport type Watermark = \"synthid\" | \"c2pa\" | (string & {})\n\n/**\n * Labelled section with absolute timing. Populated when the provider\n * returns structured section metadata (Lyria text part, ElevenLabs\n * `/v1/music/detailed` with `with_timestamps`).\n */\nexport type MusicSection = {\n readonly label: string\n readonly startSeconds: number\n readonly endSeconds: number\n}\n\n/**\n * Single generated track. Composes `AudioBlob` rather than extending\n * it — `result.audio` is the raw blob, `result.songId` / `lyrics` /\n * `sections` / `watermark` are provider-side metadata when returned.\n */\nexport type MusicResult = {\n readonly audio: AudioBlob\n /**\n * Provider identifier, useful when routing through multiple\n * providers in a single pipeline (`\"lyria\"`, `\"elevenlabs-music\"`,\n * etc.).\n */\n readonly provider?: string\n /** Provider-side ID for back-reference (re-download, extension, stems). */\n readonly songId?: string\n /** Generated or transcribed lyrics when the provider returned them. */\n readonly lyrics?: string\n /** Structured section markers when the provider returned them. */\n readonly sections?: ReadonlyArray<MusicSection>\n /** Watermark presence indicator when the provider applied one. */\n readonly watermark?: Watermark\n}\n\n/**\n * Result of a `generate` call. Suno and Mureka always return 2 tracks\n * per request; every other provider returns 1. `primary` is the\n * caller-friendly convenience; `variants` carries every track the\n * provider produced (length ≥ 1; `primary === variants[0]`).\n */\nexport type GenerateResult = {\n readonly primary: MusicResult\n readonly variants: ReadonlyArray<MusicResult>\n}\n\n/**\n * In-band event on the bidirectional `streamGenerationFrom` output\n * stream. Audio chunks flow as `audio`; server-side warnings\n * (`warning`) and prompt-filter rejections (`filteredPrompt`) flow\n * alongside rather than going to a side-channel log.\n */\nexport type MusicStreamEvent =\n | { readonly _tag: \"audio\"; readonly chunk: AudioChunk }\n | { readonly _tag: \"warning\"; readonly message: string }\n | { readonly _tag: \"filteredPrompt\"; readonly prompt: string; readonly reason: string }\n\nexport const isPromptsInput = (\n i: MusicSessionInput,\n): i is MusicSessionInput & { _tag: \"prompts\" } => i._tag === \"prompts\"\nexport const isControlInput = (\n i: MusicSessionInput,\n): i is MusicSessionInput & { _tag: \"control\" } => i._tag === \"control\"\n\nexport const audioEvent = (chunk: AudioChunk): MusicStreamEvent => ({ _tag: \"audio\", chunk })\nexport const warningEvent = (message: string): MusicStreamEvent => ({\n _tag: \"warning\",\n message,\n})\nexport const filteredPromptEvent = (prompt: string, reason: string): MusicStreamEvent => ({\n _tag: \"filteredPrompt\",\n prompt,\n reason,\n})\n\nexport const isAudioEvent = (e: MusicStreamEvent): e is MusicStreamEvent & { _tag: \"audio\" } =>\n e._tag === \"audio\"\nexport const isWarningEvent = (e: MusicStreamEvent): e is MusicStreamEvent & { _tag: \"warning\" } =>\n e._tag === \"warning\"\nexport const isFilteredPromptEvent = (\n e: MusicStreamEvent,\n): e is MusicStreamEvent & { _tag: \"filteredPrompt\" } => e._tag === \"filteredPrompt\"\n\n/**\n * Build a single-variant `GenerateResult` from a `MusicResult`.\n * Convenience for providers that always return exactly one track\n * (Lyria, ElevenLabs, MiniMax, Stable Audio, MusicGen, Riffusion,\n * Tencent). Providers that return multiple tracks (Suno, Mureka)\n * construct the `GenerateResult` directly.\n */\nexport const singleVariant = (result: MusicResult): GenerateResult => ({\n primary: result,\n variants: [result],\n})\n"],"mappings":";;;;;;;;;;;;;;;AAqFA,MAAa,gBAAgB,aAA+D;CAC1F,MAAM;CACN;CACD;AAED,MAAa,gBAAgB,YAAoD;CAC/E,MAAM;CACN;CACD;AAiED,MAAa,kBACX,MACiD,EAAE,SAAS;AAC9D,MAAa,kBACX,MACiD,EAAE,SAAS;AAE9D,MAAa,cAAc,WAAyC;CAAE,MAAM;CAAS;CAAO;AAC5F,MAAa,gBAAgB,aAAuC;CAClE,MAAM;CACN;CACD;AACD,MAAa,uBAAuB,QAAgB,YAAsC;CACxF,MAAM;CACN;CACA;CACD;AAED,MAAa,gBAAgB,MAC3B,EAAE,SAAS;AACb,MAAa,kBAAkB,MAC7B,EAAE,SAAS;AACb,MAAa,yBACX,MACuD,EAAE,SAAS;;;;;;;;AASpE,MAAa,iBAAiB,YAAyC;CACrE,SAAS;CACT,UAAU,CAAC,OAAO;CACnB"}
@@ -1,3 +1,6 @@
1
+ import { Duration } from "effect";
2
+
3
+ //#region src/domain/Transcript.d.ts
1
4
  declare namespace Transcript_d_exports {
2
5
  export { TranscriptEvent, TranscriptResult, WordTimestamp, isAudioEvent, isError, isFinal, isMetadata, isPartial, isSpeechStarted, isUtteranceEnded };
3
6
  }
@@ -5,6 +8,9 @@ declare namespace Transcript_d_exports {
5
8
  * Per-word timing + metadata. `confidence` and `speakerId` are optional
6
9
  * because providers vary widely in what they emit and when (some only on
7
10
  * final, some only with diarization enabled, some not at all).
11
+ *
12
+ * `startSeconds` / `endSeconds` stay raw `number` offsets (not `Duration`)
13
+ * — they're positions in the audio, not durations.
8
14
  */
9
15
  type WordTimestamp = {
10
16
  readonly text: string;
@@ -21,8 +27,8 @@ type WordTimestamp = {
21
27
  */
22
28
  type TranscriptResult = {
23
29
  readonly text: string;
24
- readonly languageCode?: string;
25
- readonly durationSeconds?: number;
30
+ readonly languageCode?: string; /** Total audio duration. (Word offsets stay raw seconds on `WordTimestamp`.) */
31
+ readonly duration?: Duration.Duration;
26
32
  readonly words?: ReadonlyArray<WordTimestamp>;
27
33
  readonly raw?: unknown;
28
34
  };
@@ -1 +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"}
1
+ {"version":3,"file":"Transcript.d.mts","names":[],"sources":["../../src/domain/Transcript.ts"],"mappings":";;;;;;;;;;;;;;KAUY,aAAA;EAAA,SACD,IAAA;EAAA,SACA,YAAA;EAAA,SACA,UAAA;EAAA,SACA,UAAA;EAAA,SACA,SAAA;EAAA,SACA,YAAA;AAAA;;;;;;KAQC,gBAAA;EAAA,SACD,IAAA;EAAA,SACA,YAAA,WAVA;EAAA,SAYA,QAAA,GAAW,QAAA,CAAS,QAAA;EAAA,SACpB,KAAA,GAAQ,aAAA,CAAc,aAAA;EAAA,SACtB,GAAA;AAAA;;;;;;;;;;;;;;;KAiBC,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"}
@@ -1 +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
+ {"version":3,"file":"Transcript.mjs","names":[],"sources":["../../src/domain/Transcript.ts"],"sourcesContent":["import type { Duration } from \"effect\"\n\n/**\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 *\n * `startSeconds` / `endSeconds` stay raw `number` offsets (not `Duration`)\n * — they're positions in the audio, not durations.\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 /** Total audio duration. (Word offsets stay raw seconds on `WordTimestamp`.) */\n readonly duration?: Duration.Duration\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":";;;;;;;;;;;AAuEA,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,5 +1,5 @@
1
1
  import { i as ImageSource } from "../Image-HNmMpMTh.mjs";
2
- import { d as Message, m as Reasoning, o as HistoryItem, v as ToolCall, x as Usage, y as ToolCallOutput } from "../Items-pXR5BAgW.mjs";
2
+ import { d as Message, m as Reasoning, o as HistoryItem, v as ToolCall, x as Usage, y as ToolCallOutput } from "../Items-D8UaXQx_.mjs";
3
3
  import { i as StructuredFormat, n as JsonParseError, r as StructuredDecodeError } from "../StructuredFormat-BbN4dosH.mjs";
4
4
  import { Data, Effect, Schema, Stream } from "effect";
5
5
  import * as _$effect_Types0 from "effect/Types";
@@ -2,7 +2,7 @@ import { i as ImageSource } from "../Image-HNmMpMTh.mjs";
2
2
 
3
3
  //#region src/embedding-model/Embedding.d.ts
4
4
  declare namespace Embedding_d_exports {
5
- export { BinaryEmbedding, EmbedContentPart, EmbedInput, Embedding, EmbeddingFor, Float32Embedding, Int8Embedding, MultivectorEmbedding, SparseEmbedding, Usage, isBinary, isFloat32, isInt8, isMultivector, isSparse };
5
+ export { BinaryEmbedding, EmbedContentPart, EmbedInput, Embedding, EmbeddingFor, Float32Embedding, Int8Embedding, MultivectorEmbedding, ResponseEncoding, SparseEmbedding, Usage, isBinary, isFloat32, isInt8, isMultivector, isSparse };
6
6
  }
7
7
  /**
8
8
  * One part of a mixed text+image input. Used inside `EmbedInput.content[]`
@@ -94,6 +94,16 @@ declare const isInt8: (e: Embedding) => e is Int8Embedding;
94
94
  declare const isBinary: (e: Embedding) => e is BinaryEmbedding;
95
95
  declare const isSparse: (e: Embedding) => e is SparseEmbedding;
96
96
  declare const isMultivector: (e: Embedding) => e is MultivectorEmbedding;
97
+ /**
98
+ * Domain of `EmbeddingFor` and the response type parameter on
99
+ * `EmbedResponse` / `EmbedManyResponse`: every encoding a provider can
100
+ * *return*, including Jina's widened `sparse` / `multivector`. Distinct
101
+ * from `EmbedEncoding` (the cross-provider *request* set, which is dense
102
+ * quantization only). Providers whose typed request widens beyond the
103
+ * dense set (Jina) parameterize their responses with their own encoding
104
+ * union, which is a subset of this.
105
+ */
106
+ type ResponseEncoding = "float32" | "int8" | "binary" | "sparse" | "multivector";
97
107
  /**
98
108
  * Maps an `encoding` request field to the corresponding response embedding
99
109
  * variant. `undefined` (no encoding requested) defaults to `Float32Embedding`,
@@ -115,5 +125,5 @@ type Usage = {
115
125
  readonly inputTokens?: number;
116
126
  };
117
127
  //#endregion
118
- export { BinaryEmbedding, EmbedContentPart, EmbedInput, Embedding, EmbeddingFor, Float32Embedding, Int8Embedding, MultivectorEmbedding, SparseEmbedding, Usage, isBinary, isFloat32, isInt8, isMultivector, isSparse, Embedding_d_exports as t };
128
+ export { BinaryEmbedding, EmbedContentPart, EmbedInput, Embedding, EmbeddingFor, Float32Embedding, Int8Embedding, MultivectorEmbedding, ResponseEncoding, SparseEmbedding, Usage, isBinary, isFloat32, isInt8, isMultivector, isSparse, Embedding_d_exports as t };
119
129
  //# sourceMappingURL=Embedding.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Embedding.d.mts","names":[],"sources":["../../src/embedding-model/Embedding.ts"],"mappings":";;;;;;;;;;;KAOY,gBAAA;EAAA,SAA8B,IAAA;AAAA;EAAA,SAA4B,KAAA,EAAO,WAAA;AAAA;;;;;;;;;;KAWjE,UAAA;EAAA,SAEG,IAAA;AAAA;EAAA,SACA,KAAA,EAAO,WAAA;AAAA;EAAA,SACP,OAAA,EAAS,aAAA,CAAc,gBAAA;AAAA;;KAY1B,gBAAA;EAAA,SACD,IAAA;EAAA,SACA,MAAA,EAAQ,YAAA;AAAA;;;;;KAOP,aAAA;EAAA,SACD,IAAA;EAAA,SACA,MAAA,EAAQ,SAAA;AAAA;;;;;;KAQP,eAAA;EAAA,SACD,IAAA;EAAA,SACA,MAAA,EAAQ,UAAA;AAAA;;;;;;;AAZnB;;;;;;;;;AAUA;;;KAuBY,eAAA;EAAA,SACD,IAAA;EAAA,SACA,OAAA,EAAS,QAAA,CAAS,MAAA;AAAA;;;AAF7B;;;;;;;;KAeY,oBAAA;EAAA,SACD,IAAA;EAAA,SACA,OAAA,EAAS,aAAA,CAAc,YAAA;AAAA;AAAA,KAGtB,SAAA,GACR,gBAAA,GACA,aAAA,GACA,eAAA,GACA,eAAA,GACA,oBAAA;AAAA,cAES,SAAA,GAAa,CAAA,EAAG,SAAA,KAAY,CAAA,IAAK,gBAAA;AAAA,cACjC,MAAA,GAAU,CAAA,EAAG,SAAA,KAAY,CAAA,IAAK,aAAA;AAAA,cAC9B,QAAA,GAAY,CAAA,EAAG,SAAA,KAAY,CAAA,IAAK,eAAA;AAAA,cAChC,QAAA,GAAY,CAAA,EAAG,SAAA,KAAY,CAAA,IAAK,eAAA;AAAA,cAChC,aAAA,GAAiB,CAAA,EAAG,SAAA,KAAY,CAAA,IAAK,oBAAA;;;AAXlD;;;;;;;;;KAwBY,YAAA,OAAmB,CAAA,oCAC3B,gBAAA,IACC,CAAA,qBACC,aAAA,IACC,CAAA,uBACC,eAAA,IACC,CAAA,uBACC,eAAA,IACC,CAAA,4BACC,oBAAA,GACA,SAAA;;;;;;KAOA,KAAA;EAAA,SACD,WAAA;AAAA"}
1
+ {"version":3,"file":"Embedding.d.mts","names":[],"sources":["../../src/embedding-model/Embedding.ts"],"mappings":";;;;;;;;;;;KAOY,gBAAA;EAAA,SAA8B,IAAA;AAAA;EAAA,SAA4B,KAAA,EAAO,WAAA;AAAA;;;;;;;;;;KAWjE,UAAA;EAAA,SAEG,IAAA;AAAA;EAAA,SACA,KAAA,EAAO,WAAA;AAAA;EAAA,SACP,OAAA,EAAS,aAAA,CAAc,gBAAA;AAAA;;KAY1B,gBAAA;EAAA,SACD,IAAA;EAAA,SACA,MAAA,EAAQ,YAAA;AAAA;;;;;KAOP,aAAA;EAAA,SACD,IAAA;EAAA,SACA,MAAA,EAAQ,SAAA;AAAA;;;;;;KAQP,eAAA;EAAA,SACD,IAAA;EAAA,SACA,MAAA,EAAQ,UAAA;AAAA;;;;;;;;AAZnB;;;;;;;;;AAUA;;KAuBY,eAAA;EAAA,SACD,IAAA;EAAA,SACA,OAAA,EAAS,QAAA,CAAS,MAAA;AAAA;;;;AAF7B;;;;;;;KAeY,oBAAA;EAAA,SACD,IAAA;EAAA,SACA,OAAA,EAAS,aAAA,CAAc,YAAA;AAAA;AAAA,KAGtB,SAAA,GACR,gBAAA,GACA,aAAA,GACA,eAAA,GACA,eAAA,GACA,oBAAA;AAAA,cAES,SAAA,GAAa,CAAA,EAAG,SAAA,KAAY,CAAA,IAAK,gBAAA;AAAA,cACjC,MAAA,GAAU,CAAA,EAAG,SAAA,KAAY,CAAA,IAAK,aAAA;AAAA,cAC9B,QAAA,GAAY,CAAA,EAAG,SAAA,KAAY,CAAA,IAAK,eAAA;AAAA,cAChC,QAAA,GAAY,CAAA,EAAG,SAAA,KAAY,CAAA,IAAK,eAAA;AAAA,cAChC,aAAA,GAAiB,CAAA,EAAG,SAAA,KAAY,CAAA,IAAK,oBAAA;;;;AAXlD;;;;;;KAsBY,gBAAA;;;;;;;;;;;AAfZ;KA4BY,YAAA,OAAmB,CAAA,oCAC3B,gBAAA,IACC,CAAA,qBACC,aAAA,IACC,CAAA,uBACC,eAAA,IACC,CAAA,uBACC,eAAA,IACC,CAAA,4BACC,oBAAA,GACA,SAAA;;;;;;KAOA,KAAA;EAAA,SACD,WAAA;AAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"Embedding.mjs","names":[],"sources":["../../src/embedding-model/Embedding.ts"],"sourcesContent":["import type { ImageSource } from \"../domain/Image.js\"\n\n/**\n * One part of a mixed text+image input. Used inside `EmbedInput.content[]`\n * for providers that accept interleaved modalities in a single embed call\n * (Cohere v4, Voyage multimodal, Jina v4, Google `gemini-embedding-2`).\n */\nexport type EmbedContentPart = { readonly text: string } | { readonly image: ImageSource }\n\n/**\n * What you embed. The `string` shorthand covers the common text-only case;\n * structured variants exist for image-only and mixed-modality inputs.\n *\n * Not every provider accepts every variant: text-only providers (OpenAI,\n * Mixedbread today) handle `string` and `{ text }`; multimodal providers\n * (Google, Jina v4, Voyage multimodal, Cohere v4) handle all four. A\n * provider layer rejects shapes it can't encode as `AiError.InvalidRequest`.\n */\nexport type EmbedInput =\n | string\n | { readonly text: string }\n | { readonly image: ImageSource }\n | { readonly content: ReadonlyArray<EmbedContentPart> }\n\n// ---------------------------------------------------------------------------\n// Embedding representations\n//\n// The `_tag` reflects the wire form the provider returned, *not* what the\n// consumer asked for - request `encoding: \"int8\"` and you get back an\n// `Int8Embedding`. Math primitives are typed against the named interfaces\n// (see `Vector.ts`) so e.g. `sparseCosine` only accepts `SparseEmbedding`.\n// ---------------------------------------------------------------------------\n\n/** Dense float32 vector. The default representation across all providers. */\nexport type Float32Embedding = {\n readonly _tag: \"float32\"\n readonly vector: Float32Array\n}\n\n/**\n * Dense int8-quantized vector. ~4x smaller than float32 with minimal\n * recall loss on most benchmarks.\n */\nexport type Int8Embedding = {\n readonly _tag: \"int8\"\n readonly vector: Int8Array\n}\n\n/**\n * Dense binary-quantized vector. One bit per dimension, packed into bytes.\n * ~32x smaller than float32; meaningful recall loss but useful for hot\n * indexes paired with a float32 reranker pass.\n */\nexport type BinaryEmbedding = {\n readonly _tag: \"binary\"\n readonly vector: Uint8Array\n}\n\n/**\n * Sparse vector. Token-keyed weights for hybrid search (dense + lexical-\n * style sparse). The single hosted producer today is Jina's `elser-v2`\n * model, which returns subword tokens (e.g. `\"bread\"`, `\"##ing\"`) with\n * their relevance weights.\n *\n * The shape is `Record<string, number>` rather than `(indices, values)`\n * because real hosted learned-sparse encoders (ELSER, SPLADE) emit token\n * strings with no shared vocabulary index. Converting to integer indices\n * would either need a vocabulary table the model doesn't expose, or\n * lose the cross-vector matching semantics. If a provider ever exposes\n * index-valued sparse vectors (Pinecone-style, where you bring your own\n * vocab), add an `IndexSparseEmbedding` sibling arm with `_tag:\n * \"sparse-indexed\"`.\n *\n * Score with `Vector.sparseCosine` — dot product over the intersection\n * of keys, normalized by the L2 norms of both maps.\n */\nexport type SparseEmbedding = {\n readonly _tag: \"sparse\"\n readonly weights: Readonly<Record<string, number>>\n}\n\n/**\n * Multivector / late-interaction output: one float32 vector per token.\n * Score documents with `Vector.maxSim` (ColBERT-style: per query vector,\n * max dot product across doc vectors, summed). Typically ~50-500 vectors\n * per document, each shorter than a single-vector embedding (~128 dim\n * vs ~1024).\n *\n * Quantized multivector forms aren't modeled for the same reason as\n * sparse - nothing on hosted APIs ships them yet.\n */\nexport type MultivectorEmbedding = {\n readonly _tag: \"multivector\"\n readonly vectors: ReadonlyArray<Float32Array>\n}\n\nexport type Embedding =\n | Float32Embedding\n | Int8Embedding\n | BinaryEmbedding\n | SparseEmbedding\n | MultivectorEmbedding\n\nexport const isFloat32 = (e: Embedding): e is Float32Embedding => e._tag === \"float32\"\nexport const isInt8 = (e: Embedding): e is Int8Embedding => e._tag === \"int8\"\nexport const isBinary = (e: Embedding): e is BinaryEmbedding => e._tag === \"binary\"\nexport const isSparse = (e: Embedding): e is SparseEmbedding => e._tag === \"sparse\"\nexport const isMultivector = (e: Embedding): e is MultivectorEmbedding => e._tag === \"multivector\"\n\n/**\n * Maps an `encoding` request field to the corresponding response embedding\n * variant. `undefined` (no encoding requested) defaults to `Float32Embedding`,\n * which is what every provider returns when the caller doesn't ask for\n * anything else. Widened `E` falls back to the full `Embedding` union — the\n * caller has to narrow at use site, which honestly reflects what they know\n * at compile time.\n *\n * Used by `EmbedResponse<E>` / `EmbedManyResponse<E>` to give callers a\n * precise embedding type without a runtime narrowing helper.\n */\nexport type EmbeddingFor<E> = [E] extends [undefined | \"float32\"]\n ? Float32Embedding\n : [E] extends [\"int8\"]\n ? Int8Embedding\n : [E] extends [\"binary\"]\n ? BinaryEmbedding\n : [E] extends [\"sparse\"]\n ? SparseEmbedding\n : [E] extends [\"multivector\"]\n ? MultivectorEmbedding\n : Embedding\n\n/**\n * Token usage for one embed / embedMany call. One value per HTTP request,\n * not per input vector. Most providers populate `inputTokens`; the field\n * is optional for those that don't (or for mock layers in tests).\n */\nexport type Usage = {\n readonly inputTokens?: number\n}\n"],"mappings":";;;;;;;;;AAuGA,MAAa,aAAa,MAAwC,EAAE,SAAS;AAC7E,MAAa,UAAU,MAAqC,EAAE,SAAS;AACvE,MAAa,YAAY,MAAuC,EAAE,SAAS;AAC3E,MAAa,YAAY,MAAuC,EAAE,SAAS;AAC3E,MAAa,iBAAiB,MAA4C,EAAE,SAAS"}
1
+ {"version":3,"file":"Embedding.mjs","names":[],"sources":["../../src/embedding-model/Embedding.ts"],"sourcesContent":["import type { ImageSource } from \"../domain/Image.js\"\n\n/**\n * One part of a mixed text+image input. Used inside `EmbedInput.content[]`\n * for providers that accept interleaved modalities in a single embed call\n * (Cohere v4, Voyage multimodal, Jina v4, Google `gemini-embedding-2`).\n */\nexport type EmbedContentPart = { readonly text: string } | { readonly image: ImageSource }\n\n/**\n * What you embed. The `string` shorthand covers the common text-only case;\n * structured variants exist for image-only and mixed-modality inputs.\n *\n * Not every provider accepts every variant: text-only providers (OpenAI,\n * Mixedbread today) handle `string` and `{ text }`; multimodal providers\n * (Google, Jina v4, Voyage multimodal, Cohere v4) handle all four. A\n * provider layer rejects shapes it can't encode as `AiError.InvalidRequest`.\n */\nexport type EmbedInput =\n | string\n | { readonly text: string }\n | { readonly image: ImageSource }\n | { readonly content: ReadonlyArray<EmbedContentPart> }\n\n// ---------------------------------------------------------------------------\n// Embedding representations\n//\n// The `_tag` reflects the wire form the provider returned, *not* what the\n// consumer asked for - request `encoding: \"int8\"` and you get back an\n// `Int8Embedding`. Math primitives are typed against the named interfaces\n// (see `Vector.ts`) so e.g. `sparseCosine` only accepts `SparseEmbedding`.\n// ---------------------------------------------------------------------------\n\n/** Dense float32 vector. The default representation across all providers. */\nexport type Float32Embedding = {\n readonly _tag: \"float32\"\n readonly vector: Float32Array\n}\n\n/**\n * Dense int8-quantized vector. ~4x smaller than float32 with minimal\n * recall loss on most benchmarks.\n */\nexport type Int8Embedding = {\n readonly _tag: \"int8\"\n readonly vector: Int8Array\n}\n\n/**\n * Dense binary-quantized vector. One bit per dimension, packed into bytes.\n * ~32x smaller than float32; meaningful recall loss but useful for hot\n * indexes paired with a float32 reranker pass.\n */\nexport type BinaryEmbedding = {\n readonly _tag: \"binary\"\n readonly vector: Uint8Array\n}\n\n/**\n * Sparse vector. Token-keyed weights for hybrid search (dense + lexical-\n * style sparse). The single hosted producer today is Jina's `elser-v2`\n * model, which returns subword tokens (e.g. `\"bread\"`, `\"##ing\"`) with\n * their relevance weights.\n *\n * The shape is `Record<string, number>` rather than `(indices, values)`\n * because real hosted learned-sparse encoders (ELSER, SPLADE) emit token\n * strings with no shared vocabulary index. Converting to integer indices\n * would either need a vocabulary table the model doesn't expose, or\n * lose the cross-vector matching semantics. If a provider ever exposes\n * index-valued sparse vectors (Pinecone-style, where you bring your own\n * vocab), add an `IndexSparseEmbedding` sibling arm with `_tag:\n * \"sparse-indexed\"`.\n *\n * Score with `Vector.sparseCosine` — dot product over the intersection\n * of keys, normalized by the L2 norms of both maps.\n */\nexport type SparseEmbedding = {\n readonly _tag: \"sparse\"\n readonly weights: Readonly<Record<string, number>>\n}\n\n/**\n * Multivector / late-interaction output: one float32 vector per token.\n * Score documents with `Vector.maxSim` (ColBERT-style: per query vector,\n * max dot product across doc vectors, summed). Typically ~50-500 vectors\n * per document, each shorter than a single-vector embedding (~128 dim\n * vs ~1024).\n *\n * Quantized multivector forms aren't modeled for the same reason as\n * sparse - nothing on hosted APIs ships them yet.\n */\nexport type MultivectorEmbedding = {\n readonly _tag: \"multivector\"\n readonly vectors: ReadonlyArray<Float32Array>\n}\n\nexport type Embedding =\n | Float32Embedding\n | Int8Embedding\n | BinaryEmbedding\n | SparseEmbedding\n | MultivectorEmbedding\n\nexport const isFloat32 = (e: Embedding): e is Float32Embedding => e._tag === \"float32\"\nexport const isInt8 = (e: Embedding): e is Int8Embedding => e._tag === \"int8\"\nexport const isBinary = (e: Embedding): e is BinaryEmbedding => e._tag === \"binary\"\nexport const isSparse = (e: Embedding): e is SparseEmbedding => e._tag === \"sparse\"\nexport const isMultivector = (e: Embedding): e is MultivectorEmbedding => e._tag === \"multivector\"\n\n/**\n * Domain of `EmbeddingFor` and the response type parameter on\n * `EmbedResponse` / `EmbedManyResponse`: every encoding a provider can\n * *return*, including Jina's widened `sparse` / `multivector`. Distinct\n * from `EmbedEncoding` (the cross-provider *request* set, which is dense\n * quantization only). Providers whose typed request widens beyond the\n * dense set (Jina) parameterize their responses with their own encoding\n * union, which is a subset of this.\n */\nexport type ResponseEncoding = \"float32\" | \"int8\" | \"binary\" | \"sparse\" | \"multivector\"\n\n/**\n * Maps an `encoding` request field to the corresponding response embedding\n * variant. `undefined` (no encoding requested) defaults to `Float32Embedding`,\n * which is what every provider returns when the caller doesn't ask for\n * anything else. Widened `E` falls back to the full `Embedding` union — the\n * caller has to narrow at use site, which honestly reflects what they know\n * at compile time.\n *\n * Used by `EmbedResponse<E>` / `EmbedManyResponse<E>` to give callers a\n * precise embedding type without a runtime narrowing helper.\n */\nexport type EmbeddingFor<E> = [E] extends [undefined | \"float32\"]\n ? Float32Embedding\n : [E] extends [\"int8\"]\n ? Int8Embedding\n : [E] extends [\"binary\"]\n ? BinaryEmbedding\n : [E] extends [\"sparse\"]\n ? SparseEmbedding\n : [E] extends [\"multivector\"]\n ? MultivectorEmbedding\n : Embedding\n\n/**\n * Token usage for one embed / embedMany call. One value per HTTP request,\n * not per input vector. Most providers populate `inputTokens`; the field\n * is optional for those that don't (or for mock layers in tests).\n */\nexport type Usage = {\n readonly inputTokens?: number\n}\n"],"mappings":";;;;;;;;;AAuGA,MAAa,aAAa,MAAwC,EAAE,SAAS;AAC7E,MAAa,UAAU,MAAqC,EAAE,SAAS;AACvE,MAAa,YAAY,MAAuC,EAAE,SAAS;AAC3E,MAAa,YAAY,MAAuC,EAAE,SAAS;AAC3E,MAAa,iBAAiB,MAA4C,EAAE,SAAS"}
@@ -1,33 +1,33 @@
1
1
  import { t as AiError } from "../AiError-CAX_48RU.mjs";
2
- import { EmbedInput, EmbeddingFor, Usage } from "./Embedding.mjs";
2
+ import { EmbedInput, EmbeddingFor, ResponseEncoding, Usage } from "./Embedding.mjs";
3
3
  import { Context, Effect } from "effect";
4
4
 
5
5
  //#region src/embedding-model/EmbeddingModel.d.ts
6
6
  declare namespace EmbeddingModel_d_exports {
7
- export { CommonEmbedManyRequest, CommonEmbedRequest, EmbedEncoding, EmbedManyResponse, EmbedResponse, EmbeddingModel, EmbeddingModelService, embed, embedMany };
7
+ export { CommonEmbedManyRequest, CommonEmbedRequest, EmbedEncoding, EmbedManyResponse, EmbedResponse, EmbeddingModel, EmbeddingModelService, assertEncoding, embed, embedMany };
8
8
  }
9
9
  /**
10
- * Output representation requested from the provider.
10
+ * Output representation requested from the provider. Cross-provider dense
11
+ * quantization only, the same vector at different storage cost:
12
+ * - `float32`: universal default.
13
+ * - `int8`: ~4x smaller, minimal recall loss on most benchmarks. Supported
14
+ * by Cohere, Voyage, Jina (binary only), Mixedbread.
15
+ * - `binary`: ~32x smaller, meaningful recall loss but pairs well with a
16
+ * float32 reranker pass over a small candidate set.
11
17
  *
12
- * Dense quantizations - same vector at different storage cost:
13
- * - `float32` — universal default.
14
- * - `int8` — ~4x smaller; minimal recall loss on most benchmarks.
15
- * - `binary` — ~32x smaller; meaningful recall loss but pairs well with
16
- * a float32 reranker pass over a small candidate set.
18
+ * Non-dense representations (`sparse`, `multivector`) are a different vector
19
+ * *structure*, not a storage option, and are produced by Jina only. They
20
+ * live on `JinaEncoding`, not here (the same widening pattern `task` uses).
21
+ * The response `Embedding` union still carries all arms, see
22
+ * {@link ResponseEncoding}.
17
23
  *
18
- * Non-dense representations:
19
- * - `sparse` — learned sparse vector for hybrid (dense + lexical) search.
20
- * Currently Jina ELSER only on hosted APIs.
21
- * - `multivector` — one vector per token for late-interaction (ColBERT-
22
- * style) scoring via `Vector.maxSim`. Currently Jina v4 only.
23
- *
24
- * Each provider's typed request narrows this to its supported set at
25
- * compile time (e.g. `JinaEmbedEncoding = "float32" | "binary" | "sparse" |
26
- * "multivector"`). On the generic `EmbeddingModel` path, callers can
27
- * pass any `EmbedEncoding` and the provider's API will reject mismatches at
28
- * runtime.
24
+ * Each provider's typed request narrows this to its supported set. On the
25
+ * generic `EmbeddingModel` path, a provider that emits float32 only (OpenAI,
26
+ * Gemini) rejects a non-float32 encoding with `AiError.Unsupported`
27
+ * (bucket 1) via {@link assertEncoding}, rather than silently returning a
28
+ * mislabeled float32 vector.
29
29
  */
30
- type EmbedEncoding = "float32" | "int8" | "binary" | "sparse" | "multivector";
30
+ type EmbedEncoding = "float32" | "int8" | "binary";
31
31
  /**
32
32
  * Cross-provider single-embed request. Mirrors the shape of
33
33
  * `LanguageModel.CommonRequest`: cross-cutting fields here, vendor
@@ -81,12 +81,12 @@ type CommonEmbedManyRequest = Omit<CommonEmbedRequest, "input"> & {
81
81
  * narrowing. Defaults to `undefined` for back-compat with consumers that
82
82
  * use the bare `EmbedResponse` name.
83
83
  */
84
- type EmbedResponse<E extends EmbedEncoding | undefined = undefined> = {
84
+ type EmbedResponse<E extends ResponseEncoding | undefined = undefined> = {
85
85
  readonly embedding: EmbeddingFor<E>;
86
86
  readonly usage: Usage;
87
87
  };
88
88
  /** Batch-embed response. Same encoding rule as {@link EmbedResponse}. */
89
- type EmbedManyResponse<E extends EmbedEncoding | undefined = undefined> = {
89
+ type EmbedManyResponse<E extends ResponseEncoding | undefined = undefined> = {
90
90
  readonly embeddings: ReadonlyArray<EmbeddingFor<E>>;
91
91
  readonly usage: Usage;
92
92
  };
@@ -108,6 +108,19 @@ declare const embed: <E extends EmbedEncoding | undefined = undefined>(request:
108
108
  declare const embedMany: <E extends EmbedEncoding | undefined = undefined>(request: Omit<CommonEmbedManyRequest, "encoding"> & {
109
109
  readonly encoding?: E;
110
110
  }) => Effect.Effect<EmbedManyResponse<E>, AiError, EmbeddingModel>;
111
+ /**
112
+ * Guard a requested `encoding` against a provider's supported set. Returns
113
+ * `void` when the encoding is unset or supported, and fails
114
+ * `AiError.Unsupported` (bucket 1) otherwise.
115
+ *
116
+ * Used by the generic-tag registration of providers that emit a strict
117
+ * subset of `EmbedEncoding`: OpenAI / Gemini pass `["float32"]`, Jina passes
118
+ * `["float32", "binary"]`. Without this guard, a non-supported encoding on
119
+ * the generic path silently returns a float32 vector mislabeled as the
120
+ * requested type (the `as`-cast lie), which breaks downstream storage and
121
+ * vector math.
122
+ */
123
+ declare const assertEncoding: (encoding: EmbedEncoding | undefined, supported: ReadonlyArray<EmbedEncoding>, provider: string) => Effect.Effect<void, AiError>;
111
124
  //#endregion
112
- export { CommonEmbedManyRequest, CommonEmbedRequest, EmbedEncoding, EmbedManyResponse, EmbedResponse, EmbeddingModel, EmbeddingModelService, embed, embedMany, EmbeddingModel_d_exports as t };
125
+ export { CommonEmbedManyRequest, CommonEmbedRequest, EmbedEncoding, EmbedManyResponse, EmbedResponse, EmbeddingModel, EmbeddingModelService, assertEncoding, embed, embedMany, EmbeddingModel_d_exports as t };
113
126
  //# sourceMappingURL=EmbeddingModel.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"EmbeddingModel.d.mts","names":[],"sources":["../../src/embedding-model/EmbeddingModel.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAyBA;;;;;AAYA;;KAZY,aAAA;;;;;;;;;;;KAYA,kBAAA;EAAA,SACD,KAAA,EAAO,UAAA;;;;;WAKP,KAAA;EA6BqB;;;;;;;EAAA,SArBrB,IAAA;EAqBgC;AAU3C;;;;EAV2C,SAfhC,UAAA;EA0BW;;;;;EAAA,SApBX,QAAA,GAAW,aAAA;AAAA;;;;;;KAQV,sBAAA,GAAyB,IAAA,CAAK,kBAAA;EAAA,SAC/B,MAAA,EAAQ,aAAA,CAAc,UAAA;AAAA;;;;;;;;KAUrB,aAAA,WAAwB,aAAA;EAAA,SACzB,SAAA,EAAW,YAAA,CAAa,CAAA;EAAA,SACxB,KAAA,EAAO,KAAA;AAAA;;KAIN,iBAAA,WAA4B,aAAA;EAAA,SAC7B,UAAA,EAAY,aAAA,CAAc,YAAA,CAAa,CAAA;EAAA,SACvC,KAAA,EAAO,KAAA;AAAA;AAAA,KAGN,qBAAA;EAAA,SACD,KAAA,aAAkB,aAAA,0BACzB,OAAA,EAAS,IAAA,CAAK,kBAAA;IAAA,SAA6C,QAAA,GAAW,CAAA;EAAA,MACnE,MAAA,CAAO,MAAA,CAAO,aAAA,CAAc,CAAA,GAAI,OAAA;EAAA,SAC5B,SAAA,aAAsB,aAAA,0BAC7B,OAAA,EAAS,IAAA,CAAK,sBAAA;IAAA,SAAiD,QAAA,GAAW,CAAA;EAAA,MACvE,MAAA,CAAO,MAAA,CAAO,iBAAA,CAAkB,CAAA,GAAI,OAAA;AAAA;AAAA,cAC1C,mBAAA;cAEY,cAAA,SAAuB,mBAAA;;cAKvB,KAAA,aAAmB,aAAA,0BAC9B,OAAA,EAAS,IAAA,CAAK,kBAAA;EAAA,SAA6C,QAAA,GAAW,CAAA;AAAA,MACrE,MAAA,CAAO,MAAA,CAAO,aAAA,CAAc,CAAA,GAAI,OAAA,EAAiB,cAAA;;cAIvC,SAAA,aAAuB,aAAA,0BAClC,OAAA,EAAS,IAAA,CAAK,sBAAA;EAAA,SAAiD,QAAA,GAAW,CAAA;AAAA,MACzE,MAAA,CAAO,MAAA,CAAO,iBAAA,CAAkB,CAAA,GAAI,OAAA,EAAiB,cAAA"}
1
+ {"version":3,"file":"EmbeddingModel.d.mts","names":[],"sources":["../../src/embedding-model/EmbeddingModel.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAyBA;;;;;AAYA;KAZY,aAAA;;;;;;;;;;;KAYA,kBAAA;EAAA,SACD,KAAA,EAAO,UAAA;EAiCgB;;;;EAAA,SA5BvB,KAAA;EA6BQ;;;;;;;EAAA,SArBR,IAAA;EAqBgC;;AAU3C;;;EAV2C,SAfhC,UAAA;EA0BwB;;;;;EAAA,SApBxB,QAAA,GAAW,aAAA;AAAA;;;;;;KAQV,sBAAA,GAAyB,IAAA,CAAK,kBAAA;EAAA,SAC/B,MAAA,EAAQ,aAAA,CAAc,UAAA;AAAA;;;;;;;;KAUrB,aAAA,WAAwB,gBAAA;EAAA,SACzB,SAAA,EAAW,YAAA,CAAa,CAAA;EAAA,SACxB,KAAA,EAAO,KAAA;AAAA;;KAIN,iBAAA,WAA4B,gBAAA;EAAA,SAC7B,UAAA,EAAY,aAAA,CAAc,YAAA,CAAa,CAAA;EAAA,SACvC,KAAA,EAAO,KAAA;AAAA;AAAA,KAGN,qBAAA;EAAA,SACD,KAAA,aAAkB,aAAA,0BACzB,OAAA,EAAS,IAAA,CAAK,kBAAA;IAAA,SAA6C,QAAA,GAAW,CAAA;EAAA,MACnE,MAAA,CAAO,MAAA,CAAO,aAAA,CAAc,CAAA,GAAI,OAAA;EAAA,SAC5B,SAAA,aAAsB,aAAA,0BAC7B,OAAA,EAAS,IAAA,CAAK,sBAAA;IAAA,SAAiD,QAAA,GAAW,CAAA;EAAA,MACvE,MAAA,CAAO,MAAA,CAAO,iBAAA,CAAkB,CAAA,GAAI,OAAA;AAAA;AAAA,cAC1C,mBAAA;cAEY,cAAA,SAAuB,mBAAA;;cAKvB,KAAA,aAAmB,aAAA,0BAC9B,OAAA,EAAS,IAAA,CAAK,kBAAA;EAAA,SAA6C,QAAA,GAAW,CAAA;AAAA,MACrE,MAAA,CAAO,MAAA,CAAO,aAAA,CAAc,CAAA,GAAI,OAAA,EAAiB,cAAA;;cAIvC,SAAA,aAAuB,aAAA,0BAClC,OAAA,EAAS,IAAA,CAAK,sBAAA;EAAA,SAAiD,QAAA,GAAW,CAAA;AAAA,MACzE,MAAA,CAAO,MAAA,CAAO,iBAAA,CAAkB,CAAA,GAAI,OAAA,EAAiB,cAAA;;;;;;;;;;;;;cAe3C,cAAA,GACX,QAAA,EAAU,aAAA,cACV,SAAA,EAAW,aAAA,CAAc,aAAA,GACzB,QAAA,aACC,MAAA,CAAO,MAAA,OAAa,OAAA"}
@@ -1,8 +1,10 @@
1
1
  import { n as __exportAll } from "../chunk-uyGKjUfl.mjs";
2
+ import { Unsupported } from "../domain/AiError.mjs";
2
3
  import { Context, Effect } from "effect";
3
4
  //#region src/embedding-model/EmbeddingModel.ts
4
5
  var EmbeddingModel_exports = /* @__PURE__ */ __exportAll({
5
6
  EmbeddingModel: () => EmbeddingModel,
7
+ assertEncoding: () => assertEncoding,
6
8
  embed: () => embed,
7
9
  embedMany: () => embedMany
8
10
  });
@@ -11,7 +13,24 @@ var EmbeddingModel = class extends Context.Service()("@betalyra/effect-uai/Embed
11
13
  const embed = (request) => Effect.flatMap(EmbeddingModel.asEffect(), (m) => m.embed(request));
12
14
  /** Embed a batch in one provider call. Same `task` for every input. */
13
15
  const embedMany = (request) => Effect.flatMap(EmbeddingModel.asEffect(), (m) => m.embedMany(request));
16
+ /**
17
+ * Guard a requested `encoding` against a provider's supported set. Returns
18
+ * `void` when the encoding is unset or supported, and fails
19
+ * `AiError.Unsupported` (bucket 1) otherwise.
20
+ *
21
+ * Used by the generic-tag registration of providers that emit a strict
22
+ * subset of `EmbedEncoding`: OpenAI / Gemini pass `["float32"]`, Jina passes
23
+ * `["float32", "binary"]`. Without this guard, a non-supported encoding on
24
+ * the generic path silently returns a float32 vector mislabeled as the
25
+ * requested type (the `as`-cast lie), which breaks downstream storage and
26
+ * vector math.
27
+ */
28
+ const assertEncoding = (encoding, supported, provider) => encoding === void 0 || supported.includes(encoding) ? Effect.void : Effect.fail(new Unsupported({
29
+ provider,
30
+ capability: "encoding",
31
+ reason: `${provider} emits ${supported.join(" / ")} only; encoding="${encoding}" is unavailable.`
32
+ }));
14
33
  //#endregion
15
- export { EmbeddingModel, embed, embedMany, EmbeddingModel_exports as t };
34
+ export { EmbeddingModel, assertEncoding, embed, embedMany, EmbeddingModel_exports as t };
16
35
 
17
36
  //# sourceMappingURL=EmbeddingModel.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"EmbeddingModel.mjs","names":[],"sources":["../../src/embedding-model/EmbeddingModel.ts"],"sourcesContent":["import { Context, Effect } from \"effect\"\nimport * as AiError from \"../domain/AiError.js\"\nimport type { EmbeddingFor, EmbedInput, Usage } from \"./Embedding.js\"\n\n/**\n * Output representation requested from the provider.\n *\n * Dense quantizations - same vector at different storage cost:\n * - `float32` — universal default.\n * - `int8` — ~4x smaller; minimal recall loss on most benchmarks.\n * - `binary` — ~32x smaller; meaningful recall loss but pairs well with\n * a float32 reranker pass over a small candidate set.\n *\n * Non-dense representations:\n * - `sparse` — learned sparse vector for hybrid (dense + lexical) search.\n * Currently Jina ELSER only on hosted APIs.\n * - `multivector` — one vector per token for late-interaction (ColBERT-\n * style) scoring via `Vector.maxSim`. Currently Jina v4 only.\n *\n * Each provider's typed request narrows this to its supported set at\n * compile time (e.g. `JinaEmbedEncoding = \"float32\" | \"binary\" | \"sparse\" |\n * \"multivector\"`). On the generic `EmbeddingModel` path, callers can\n * pass any `EmbedEncoding` and the provider's API will reject mismatches at\n * runtime.\n */\nexport type EmbedEncoding = \"float32\" | \"int8\" | \"binary\" | \"sparse\" | \"multivector\"\n\n/**\n * Cross-provider single-embed request. Mirrors the shape of\n * `LanguageModel.CommonRequest`: cross-cutting fields here, vendor\n * specifics in the provider's typed request.\n *\n * Provider-specific extensions (Cohere widened `task` enum, Jina LoRA\n * tasks, Mixedbread free-form `prompt`, etc.) live in that provider's own\n * request interface, which extends this and narrows `model` / widens\n * `task`.\n */\nexport type CommonEmbedRequest = {\n readonly input: EmbedInput\n /**\n * Model identifier. Each provider narrows this to its typed literal\n * union, so code that yields a typed provider tag gets autocompletion.\n */\n readonly model: string\n /**\n * Retrieval-task hint. Applies to the input. OpenAI ignores this;\n * Mixedbread doesn't have it; Cohere v3+ requires it on the wire (typed\n * as required in `CohereEmbedRequest`). Provider-specific task enums\n * (classification, clustering, code retrieval, …) live on the\n * provider's own request type.\n */\n readonly task?: \"query\" | \"document\"\n /**\n * Matryoshka truncation. Default: provider's native dimension.\n * Discrete-value providers (Cohere, Vertex `multimodalembedding@001`)\n * narrow this to a literal union in their typed request.\n */\n readonly dimensions?: number\n /**\n * Output representation - see {@link EmbedEncoding}. Dense float32 is the\n * default; provider layers reject unsupported values up front with\n * `InvalidRequest`.\n */\n readonly encoding?: EmbedEncoding\n}\n\n/**\n * Cross-provider batch-embed request. One `task` for the whole batch -\n * mixed-task batches aren't a real provider feature (rerankers exist for\n * that).\n */\nexport type CommonEmbedManyRequest = Omit<CommonEmbedRequest, \"input\"> & {\n readonly inputs: ReadonlyArray<EmbedInput>\n}\n\n/**\n * Single-embed response. The `embedding` type is determined by the\n * request's `encoding` field via `EmbeddingFor<E>` — callers that don't\n * specify an encoding get a `Float32Embedding` directly with no runtime\n * narrowing. Defaults to `undefined` for back-compat with consumers that\n * use the bare `EmbedResponse` name.\n */\nexport type EmbedResponse<E extends EmbedEncoding | undefined = undefined> = {\n readonly embedding: EmbeddingFor<E>\n readonly usage: Usage\n}\n\n/** Batch-embed response. Same encoding rule as {@link EmbedResponse}. */\nexport type EmbedManyResponse<E extends EmbedEncoding | undefined = undefined> = {\n readonly embeddings: ReadonlyArray<EmbeddingFor<E>>\n readonly usage: Usage\n}\n\nexport type EmbeddingModelService = {\n readonly embed: <E extends EmbedEncoding | undefined = undefined>(\n request: Omit<CommonEmbedRequest, \"encoding\"> & { readonly encoding?: E },\n ) => Effect.Effect<EmbedResponse<E>, AiError.AiError>\n readonly embedMany: <E extends EmbedEncoding | undefined = undefined>(\n request: Omit<CommonEmbedManyRequest, \"encoding\"> & { readonly encoding?: E },\n ) => Effect.Effect<EmbedManyResponse<E>, AiError.AiError>\n}\n\nexport class EmbeddingModel extends Context.Service<EmbeddingModel, EmbeddingModelService>()(\n \"@betalyra/effect-uai/EmbeddingModel\",\n) {}\n\n/** Embed a single input. */\nexport const embed = <E extends EmbedEncoding | undefined = undefined>(\n request: Omit<CommonEmbedRequest, \"encoding\"> & { readonly encoding?: E },\n): Effect.Effect<EmbedResponse<E>, AiError.AiError, EmbeddingModel> =>\n Effect.flatMap(EmbeddingModel.asEffect(), (m) => m.embed(request))\n\n/** Embed a batch in one provider call. Same `task` for every input. */\nexport const embedMany = <E extends EmbedEncoding | undefined = undefined>(\n request: Omit<CommonEmbedManyRequest, \"encoding\"> & { readonly encoding?: E },\n): Effect.Effect<EmbedManyResponse<E>, AiError.AiError, EmbeddingModel> =>\n Effect.flatMap(EmbeddingModel.asEffect(), (m) => m.embedMany(request))\n"],"mappings":";;;;;;;;AAsGA,IAAa,iBAAb,cAAoC,QAAQ,SAAgD,CAC1F,sCACD,CAAC;;AAGF,MAAa,SACX,YAEA,OAAO,QAAQ,eAAe,UAAU,GAAG,MAAM,EAAE,MAAM,QAAQ,CAAC;;AAGpE,MAAa,aACX,YAEA,OAAO,QAAQ,eAAe,UAAU,GAAG,MAAM,EAAE,UAAU,QAAQ,CAAC"}
1
+ {"version":3,"file":"EmbeddingModel.mjs","names":["AiError.Unsupported"],"sources":["../../src/embedding-model/EmbeddingModel.ts"],"sourcesContent":["import { Context, Effect } from \"effect\"\nimport * as AiError from \"../domain/AiError.js\"\nimport type { EmbeddingFor, EmbedInput, ResponseEncoding, Usage } from \"./Embedding.js\"\n\n/**\n * Output representation requested from the provider. Cross-provider dense\n * quantization only, the same vector at different storage cost:\n * - `float32`: universal default.\n * - `int8`: ~4x smaller, minimal recall loss on most benchmarks. Supported\n * by Cohere, Voyage, Jina (binary only), Mixedbread.\n * - `binary`: ~32x smaller, meaningful recall loss but pairs well with a\n * float32 reranker pass over a small candidate set.\n *\n * Non-dense representations (`sparse`, `multivector`) are a different vector\n * *structure*, not a storage option, and are produced by Jina only. They\n * live on `JinaEncoding`, not here (the same widening pattern `task` uses).\n * The response `Embedding` union still carries all arms, see\n * {@link ResponseEncoding}.\n *\n * Each provider's typed request narrows this to its supported set. On the\n * generic `EmbeddingModel` path, a provider that emits float32 only (OpenAI,\n * Gemini) rejects a non-float32 encoding with `AiError.Unsupported`\n * (bucket 1) via {@link assertEncoding}, rather than silently returning a\n * mislabeled float32 vector.\n */\nexport type EmbedEncoding = \"float32\" | \"int8\" | \"binary\"\n\n/**\n * Cross-provider single-embed request. Mirrors the shape of\n * `LanguageModel.CommonRequest`: cross-cutting fields here, vendor\n * specifics in the provider's typed request.\n *\n * Provider-specific extensions (Cohere widened `task` enum, Jina LoRA\n * tasks, Mixedbread free-form `prompt`, etc.) live in that provider's own\n * request interface, which extends this and narrows `model` / widens\n * `task`.\n */\nexport type CommonEmbedRequest = {\n readonly input: EmbedInput\n /**\n * Model identifier. Each provider narrows this to its typed literal\n * union, so code that yields a typed provider tag gets autocompletion.\n */\n readonly model: string\n /**\n * Retrieval-task hint. Applies to the input. OpenAI ignores this;\n * Mixedbread doesn't have it; Cohere v3+ requires it on the wire (typed\n * as required in `CohereEmbedRequest`). Provider-specific task enums\n * (classification, clustering, code retrieval, …) live on the\n * provider's own request type.\n */\n readonly task?: \"query\" | \"document\"\n /**\n * Matryoshka truncation. Default: provider's native dimension.\n * Discrete-value providers (Cohere, Vertex `multimodalembedding@001`)\n * narrow this to a literal union in their typed request.\n */\n readonly dimensions?: number\n /**\n * Output representation - see {@link EmbedEncoding}. Dense float32 is the\n * default; provider layers reject unsupported values up front with\n * `InvalidRequest`.\n */\n readonly encoding?: EmbedEncoding\n}\n\n/**\n * Cross-provider batch-embed request. One `task` for the whole batch -\n * mixed-task batches aren't a real provider feature (rerankers exist for\n * that).\n */\nexport type CommonEmbedManyRequest = Omit<CommonEmbedRequest, \"input\"> & {\n readonly inputs: ReadonlyArray<EmbedInput>\n}\n\n/**\n * Single-embed response. The `embedding` type is determined by the\n * request's `encoding` field via `EmbeddingFor<E>` — callers that don't\n * specify an encoding get a `Float32Embedding` directly with no runtime\n * narrowing. Defaults to `undefined` for back-compat with consumers that\n * use the bare `EmbedResponse` name.\n */\nexport type EmbedResponse<E extends ResponseEncoding | undefined = undefined> = {\n readonly embedding: EmbeddingFor<E>\n readonly usage: Usage\n}\n\n/** Batch-embed response. Same encoding rule as {@link EmbedResponse}. */\nexport type EmbedManyResponse<E extends ResponseEncoding | undefined = undefined> = {\n readonly embeddings: ReadonlyArray<EmbeddingFor<E>>\n readonly usage: Usage\n}\n\nexport type EmbeddingModelService = {\n readonly embed: <E extends EmbedEncoding | undefined = undefined>(\n request: Omit<CommonEmbedRequest, \"encoding\"> & { readonly encoding?: E },\n ) => Effect.Effect<EmbedResponse<E>, AiError.AiError>\n readonly embedMany: <E extends EmbedEncoding | undefined = undefined>(\n request: Omit<CommonEmbedManyRequest, \"encoding\"> & { readonly encoding?: E },\n ) => Effect.Effect<EmbedManyResponse<E>, AiError.AiError>\n}\n\nexport class EmbeddingModel extends Context.Service<EmbeddingModel, EmbeddingModelService>()(\n \"@betalyra/effect-uai/EmbeddingModel\",\n) {}\n\n/** Embed a single input. */\nexport const embed = <E extends EmbedEncoding | undefined = undefined>(\n request: Omit<CommonEmbedRequest, \"encoding\"> & { readonly encoding?: E },\n): Effect.Effect<EmbedResponse<E>, AiError.AiError, EmbeddingModel> =>\n Effect.flatMap(EmbeddingModel.asEffect(), (m) => m.embed(request))\n\n/** Embed a batch in one provider call. Same `task` for every input. */\nexport const embedMany = <E extends EmbedEncoding | undefined = undefined>(\n request: Omit<CommonEmbedManyRequest, \"encoding\"> & { readonly encoding?: E },\n): Effect.Effect<EmbedManyResponse<E>, AiError.AiError, EmbeddingModel> =>\n Effect.flatMap(EmbeddingModel.asEffect(), (m) => m.embedMany(request))\n\n/**\n * Guard a requested `encoding` against a provider's supported set. Returns\n * `void` when the encoding is unset or supported, and fails\n * `AiError.Unsupported` (bucket 1) otherwise.\n *\n * Used by the generic-tag registration of providers that emit a strict\n * subset of `EmbedEncoding`: OpenAI / Gemini pass `[\"float32\"]`, Jina passes\n * `[\"float32\", \"binary\"]`. Without this guard, a non-supported encoding on\n * the generic path silently returns a float32 vector mislabeled as the\n * requested type (the `as`-cast lie), which breaks downstream storage and\n * vector math.\n */\nexport const assertEncoding = (\n encoding: EmbedEncoding | undefined,\n supported: ReadonlyArray<EmbedEncoding>,\n provider: string,\n): Effect.Effect<void, AiError.AiError> =>\n encoding === undefined || supported.includes(encoding)\n ? Effect.void\n : Effect.fail(\n new AiError.Unsupported({\n provider,\n capability: \"encoding\",\n reason: `${provider} emits ${supported.join(\" / \")} only; encoding=\"${encoding}\" is unavailable.`,\n }),\n )\n"],"mappings":";;;;;;;;;;AAsGA,IAAa,iBAAb,cAAoC,QAAQ,SAAgD,CAC1F,sCACD,CAAC;;AAGF,MAAa,SACX,YAEA,OAAO,QAAQ,eAAe,UAAU,GAAG,MAAM,EAAE,MAAM,QAAQ,CAAC;;AAGpE,MAAa,aACX,YAEA,OAAO,QAAQ,eAAe,UAAU,GAAG,MAAM,EAAE,UAAU,QAAQ,CAAC;;;;;;;;;;;;;AAcxE,MAAa,kBACX,UACA,WACA,aAEA,aAAa,KAAA,KAAa,UAAU,SAAS,SAAS,GAClD,OAAO,OACP,OAAO,KACL,IAAIA,YAAoB;CACtB;CACA,YAAY;CACZ,QAAQ,GAAG,SAAS,SAAS,UAAU,KAAK,MAAM,CAAC,mBAAmB,SAAS;CAChF,CAAC,CACH"}
@@ -5,7 +5,7 @@ describe("EmbedResponse<E> conditional narrowing", () => {
5
5
  it("defaults to Float32Embedding when E is undefined", () => {
6
6
  (0, import_dist.expectTypeOf)().toEqualTypeOf();
7
7
  });
8
- it("maps each EmbedEncoding literal to the matching Embedding variant", () => {
8
+ it("maps each encoding literal to the matching Embedding variant", () => {
9
9
  (0, import_dist.expectTypeOf)().toEqualTypeOf();
10
10
  (0, import_dist.expectTypeOf)().toEqualTypeOf();
11
11
  (0, import_dist.expectTypeOf)().toEqualTypeOf();
@@ -38,13 +38,25 @@ describe("embed / embedMany free exports preserve E in their return type", () =>
38
38
  encoding: "int8"
39
39
  })).toEqualTypeOf();
40
40
  });
41
- it("embedMany with encoding: multivector returns EmbedManyResponse<multivector>", () => {
41
+ it("embedMany with encoding: binary returns EmbedManyResponse<binary>", () => {
42
42
  (0, import_dist.expectTypeOf)(embedMany({
43
43
  inputs: ["x"],
44
44
  model: "m",
45
- encoding: "multivector"
45
+ encoding: "binary"
46
46
  })).toEqualTypeOf();
47
47
  });
48
+ it("rejects non-dense encodings on the generic path (trimmed EmbedEncoding)", () => {
49
+ embedMany({
50
+ inputs: ["x"],
51
+ model: "m",
52
+ encoding: "multivector"
53
+ });
54
+ embed({
55
+ input: "x",
56
+ model: "m",
57
+ encoding: "sparse"
58
+ });
59
+ });
48
60
  it("when the request is widened to CommonEmbedRequest, the response is the open union", () => {
49
61
  (0, import_dist.expectTypeOf)(embed({
50
62
  input: "x",
@@ -1 +1 @@
1
- {"version":3,"file":"EmbeddingModel.test.mjs","names":[],"sources":["../../src/embedding-model/EmbeddingModel.test.ts"],"sourcesContent":["import { Effect } from \"effect\"\nimport { describe, expectTypeOf, it } from \"vitest\"\nimport type * as AiError from \"../domain/AiError.js\"\nimport type {\n BinaryEmbedding,\n Float32Embedding,\n Int8Embedding,\n MultivectorEmbedding,\n SparseEmbedding,\n} from \"./Embedding.js\"\nimport {\n type EmbedEncoding,\n embed,\n embedMany,\n type EmbedManyResponse,\n type EmbedResponse,\n EmbeddingModel,\n} from \"./EmbeddingModel.js\"\n\n// Type-level tests only. The actual narrowing happens at the type system\n// boundary — the runtime impl is exercised in provider-specific test files.\ndescribe(\"EmbedResponse<E> conditional narrowing\", () => {\n it(\"defaults to Float32Embedding when E is undefined\", () => {\n expectTypeOf<EmbedResponse>().toEqualTypeOf<{\n readonly embedding: Float32Embedding\n readonly usage: import(\"./Embedding.js\").Usage\n }>()\n })\n\n it(\"maps each EmbedEncoding literal to the matching Embedding variant\", () => {\n expectTypeOf<EmbedResponse<\"float32\">[\"embedding\"]>().toEqualTypeOf<Float32Embedding>()\n expectTypeOf<EmbedResponse<\"int8\">[\"embedding\"]>().toEqualTypeOf<Int8Embedding>()\n expectTypeOf<EmbedResponse<\"binary\">[\"embedding\"]>().toEqualTypeOf<BinaryEmbedding>()\n expectTypeOf<EmbedResponse<\"sparse\">[\"embedding\"]>().toEqualTypeOf<SparseEmbedding>()\n expectTypeOf<EmbedResponse<\"multivector\">[\"embedding\"]>().toEqualTypeOf<MultivectorEmbedding>()\n })\n\n it(\"falls back to the open Embedding union when E is the full EmbedEncoding\", () => {\n expectTypeOf<EmbedResponse<EmbedEncoding>[\"embedding\"]>().toEqualTypeOf<\n Float32Embedding | Int8Embedding | BinaryEmbedding | SparseEmbedding | MultivectorEmbedding\n >()\n })\n})\n\ndescribe(\"EmbedManyResponse<E> mirrors EmbedResponse<E>\", () => {\n it(\"defaults to ReadonlyArray<Float32Embedding>\", () => {\n expectTypeOf<EmbedManyResponse[\"embeddings\"]>().toEqualTypeOf<ReadonlyArray<Float32Embedding>>()\n })\n\n it(\"narrows per encoding\", () => {\n expectTypeOf<EmbedManyResponse<\"int8\">[\"embeddings\"]>().toEqualTypeOf<\n ReadonlyArray<Int8Embedding>\n >()\n })\n})\n\ndescribe(\"embed / embedMany free exports preserve E in their return type\", () => {\n it(\"embed with no encoding returns EmbedResponse<undefined> = Float32\", () => {\n const result = embed({ input: \"x\", model: \"m\" })\n expectTypeOf(result).toEqualTypeOf<\n Effect.Effect<EmbedResponse<undefined>, AiError.AiError, EmbeddingModel>\n >()\n })\n\n it(\"embed with encoding: int8 returns EmbedResponse<int8>\", () => {\n const result = embed({ input: \"x\", model: \"m\", encoding: \"int8\" })\n expectTypeOf(result).toEqualTypeOf<\n Effect.Effect<EmbedResponse<\"int8\">, AiError.AiError, EmbeddingModel>\n >()\n })\n\n it(\"embedMany with encoding: multivector returns EmbedManyResponse<multivector>\", () => {\n const result = embedMany({ inputs: [\"x\"], model: \"m\", encoding: \"multivector\" })\n expectTypeOf(result).toEqualTypeOf<\n Effect.Effect<EmbedManyResponse<\"multivector\">, AiError.AiError, EmbeddingModel>\n >()\n })\n\n it(\"when the request is widened to CommonEmbedRequest, the response is the open union\", () => {\n // Demonstrates the documented case: annotating the request type erases\n // the literal `encoding` and the response falls back to `Embedding`.\n const req: { input: string; model: string; encoding?: EmbedEncoding } = {\n input: \"x\",\n model: \"m\",\n encoding: \"int8\",\n }\n const result = embed(req)\n expectTypeOf(result).toEqualTypeOf<\n Effect.Effect<EmbedResponse<EmbedEncoding>, AiError.AiError, EmbeddingModel>\n >()\n })\n})\n"],"mappings":";;;AAqBA,SAAS,gDAAgD;AACvD,IAAG,0DAA0D;AAC3D,GAAA,GAAA,YAAA,eAA6B,CAAC,eAG1B;GACJ;AAEF,IAAG,2EAA2E;AAC5E,GAAA,GAAA,YAAA,eAAqD,CAAC,eAAiC;AACvF,GAAA,GAAA,YAAA,eAAkD,CAAC,eAA8B;AACjF,GAAA,GAAA,YAAA,eAAoD,CAAC,eAAgC;AACrF,GAAA,GAAA,YAAA,eAAoD,CAAC,eAAgC;AACrF,GAAA,GAAA,YAAA,eAAyD,CAAC,eAAqC;GAC/F;AAEF,IAAG,iFAAiF;AAClF,GAAA,GAAA,YAAA,eAAyD,CAAC,eAEvD;GACH;EACF;AAEF,SAAS,uDAAuD;AAC9D,IAAG,qDAAqD;AACtD,GAAA,GAAA,YAAA,eAA+C,CAAC,eAAgD;GAChG;AAEF,IAAG,8BAA8B;AAC/B,GAAA,GAAA,YAAA,eAAuD,CAAC,eAErD;GACH;EACF;AAEF,SAAS,wEAAwE;AAC/E,IAAG,2EAA2E;AAE5E,GAAA,GAAA,YAAA,cADe,MAAM;GAAE,OAAO;GAAK,OAAO;GAAK,CAC5B,CAAC,CAAC,eAElB;GACH;AAEF,IAAG,+DAA+D;AAEhE,GAAA,GAAA,YAAA,cADe,MAAM;GAAE,OAAO;GAAK,OAAO;GAAK,UAAU;GAAQ,CAC9C,CAAC,CAAC,eAElB;GACH;AAEF,IAAG,qFAAqF;AAEtF,GAAA,GAAA,YAAA,cADe,UAAU;GAAE,QAAQ,CAAC,IAAI;GAAE,OAAO;GAAK,UAAU;GAAe,CAC5D,CAAC,CAAC,eAElB;GACH;AAEF,IAAG,2FAA2F;AAS5F,GAAA,GAAA,YAAA,cADe,MAAM;GAJnB,OAAO;GACP,OAAO;GACP,UAAU;GAEY,CACL,CAAC,CAAC,eAElB;GACH;EACF"}
1
+ {"version":3,"file":"EmbeddingModel.test.mjs","names":[],"sources":["../../src/embedding-model/EmbeddingModel.test.ts"],"sourcesContent":["import { Effect } from \"effect\"\nimport { describe, expectTypeOf, it } from \"vitest\"\nimport type * as AiError from \"../domain/AiError.js\"\nimport type {\n BinaryEmbedding,\n Float32Embedding,\n Int8Embedding,\n MultivectorEmbedding,\n SparseEmbedding,\n} from \"./Embedding.js\"\nimport {\n type EmbedEncoding,\n embed,\n embedMany,\n type EmbedManyResponse,\n type EmbedResponse,\n EmbeddingModel,\n} from \"./EmbeddingModel.js\"\n\n// Type-level tests only. The actual narrowing happens at the type system\n// boundary — the runtime impl is exercised in provider-specific test files.\ndescribe(\"EmbedResponse<E> conditional narrowing\", () => {\n it(\"defaults to Float32Embedding when E is undefined\", () => {\n expectTypeOf<EmbedResponse>().toEqualTypeOf<{\n readonly embedding: Float32Embedding\n readonly usage: import(\"./Embedding.js\").Usage\n }>()\n })\n\n it(\"maps each encoding literal to the matching Embedding variant\", () => {\n expectTypeOf<EmbedResponse<\"float32\">[\"embedding\"]>().toEqualTypeOf<Float32Embedding>()\n expectTypeOf<EmbedResponse<\"int8\">[\"embedding\"]>().toEqualTypeOf<Int8Embedding>()\n expectTypeOf<EmbedResponse<\"binary\">[\"embedding\"]>().toEqualTypeOf<BinaryEmbedding>()\n expectTypeOf<EmbedResponse<\"sparse\">[\"embedding\"]>().toEqualTypeOf<SparseEmbedding>()\n expectTypeOf<EmbedResponse<\"multivector\">[\"embedding\"]>().toEqualTypeOf<MultivectorEmbedding>()\n })\n\n it(\"falls back to the open Embedding union when E is the full EmbedEncoding\", () => {\n expectTypeOf<EmbedResponse<EmbedEncoding>[\"embedding\"]>().toEqualTypeOf<\n Float32Embedding | Int8Embedding | BinaryEmbedding | SparseEmbedding | MultivectorEmbedding\n >()\n })\n})\n\ndescribe(\"EmbedManyResponse<E> mirrors EmbedResponse<E>\", () => {\n it(\"defaults to ReadonlyArray<Float32Embedding>\", () => {\n expectTypeOf<EmbedManyResponse[\"embeddings\"]>().toEqualTypeOf<ReadonlyArray<Float32Embedding>>()\n })\n\n it(\"narrows per encoding\", () => {\n expectTypeOf<EmbedManyResponse<\"int8\">[\"embeddings\"]>().toEqualTypeOf<\n ReadonlyArray<Int8Embedding>\n >()\n })\n})\n\ndescribe(\"embed / embedMany free exports preserve E in their return type\", () => {\n it(\"embed with no encoding returns EmbedResponse<undefined> = Float32\", () => {\n const result = embed({ input: \"x\", model: \"m\" })\n expectTypeOf(result).toEqualTypeOf<\n Effect.Effect<EmbedResponse<undefined>, AiError.AiError, EmbeddingModel>\n >()\n })\n\n it(\"embed with encoding: int8 returns EmbedResponse<int8>\", () => {\n const result = embed({ input: \"x\", model: \"m\", encoding: \"int8\" })\n expectTypeOf(result).toEqualTypeOf<\n Effect.Effect<EmbedResponse<\"int8\">, AiError.AiError, EmbeddingModel>\n >()\n })\n\n it(\"embedMany with encoding: binary returns EmbedManyResponse<binary>\", () => {\n const result = embedMany({ inputs: [\"x\"], model: \"m\", encoding: \"binary\" })\n expectTypeOf(result).toEqualTypeOf<\n Effect.Effect<EmbedManyResponse<\"binary\">, AiError.AiError, EmbeddingModel>\n >()\n })\n\n it(\"rejects non-dense encodings on the generic path (trimmed EmbedEncoding)\", () => {\n // `sparse` / `multivector` are Jina-only representation kinds, not part\n // of the cross-provider request set. Requesting them on the generic\n // helper is a compile error; they're reachable only via the typed\n // `JinaEmbedding` tag.\n // @ts-expect-error \"multivector\" is not an EmbedEncoding\n embedMany({ inputs: [\"x\"], model: \"m\", encoding: \"multivector\" })\n // @ts-expect-error \"sparse\" is not an EmbedEncoding\n embed({ input: \"x\", model: \"m\", encoding: \"sparse\" })\n })\n\n it(\"when the request is widened to CommonEmbedRequest, the response is the open union\", () => {\n // Demonstrates the documented case: annotating the request type erases\n // the literal `encoding` and the response falls back to `Embedding`.\n const req: { input: string; model: string; encoding?: EmbedEncoding } = {\n input: \"x\",\n model: \"m\",\n encoding: \"int8\",\n }\n const result = embed(req)\n expectTypeOf(result).toEqualTypeOf<\n Effect.Effect<EmbedResponse<EmbedEncoding>, AiError.AiError, EmbeddingModel>\n >()\n })\n})\n"],"mappings":";;;AAqBA,SAAS,gDAAgD;AACvD,IAAG,0DAA0D;AAC3D,GAAA,GAAA,YAAA,eAA6B,CAAC,eAG1B;GACJ;AAEF,IAAG,sEAAsE;AACvE,GAAA,GAAA,YAAA,eAAqD,CAAC,eAAiC;AACvF,GAAA,GAAA,YAAA,eAAkD,CAAC,eAA8B;AACjF,GAAA,GAAA,YAAA,eAAoD,CAAC,eAAgC;AACrF,GAAA,GAAA,YAAA,eAAoD,CAAC,eAAgC;AACrF,GAAA,GAAA,YAAA,eAAyD,CAAC,eAAqC;GAC/F;AAEF,IAAG,iFAAiF;AAClF,GAAA,GAAA,YAAA,eAAyD,CAAC,eAEvD;GACH;EACF;AAEF,SAAS,uDAAuD;AAC9D,IAAG,qDAAqD;AACtD,GAAA,GAAA,YAAA,eAA+C,CAAC,eAAgD;GAChG;AAEF,IAAG,8BAA8B;AAC/B,GAAA,GAAA,YAAA,eAAuD,CAAC,eAErD;GACH;EACF;AAEF,SAAS,wEAAwE;AAC/E,IAAG,2EAA2E;AAE5E,GAAA,GAAA,YAAA,cADe,MAAM;GAAE,OAAO;GAAK,OAAO;GAAK,CAC5B,CAAC,CAAC,eAElB;GACH;AAEF,IAAG,+DAA+D;AAEhE,GAAA,GAAA,YAAA,cADe,MAAM;GAAE,OAAO;GAAK,OAAO;GAAK,UAAU;GAAQ,CAC9C,CAAC,CAAC,eAElB;GACH;AAEF,IAAG,2EAA2E;AAE5E,GAAA,GAAA,YAAA,cADe,UAAU;GAAE,QAAQ,CAAC,IAAI;GAAE,OAAO;GAAK,UAAU;GAAU,CACvD,CAAC,CAAC,eAElB;GACH;AAEF,IAAG,iFAAiF;AAMlF,YAAU;GAAE,QAAQ,CAAC,IAAI;GAAE,OAAO;GAAK,UAAU;GAAe,CAAC;AAEjE,QAAM;GAAE,OAAO;GAAK,OAAO;GAAK,UAAU;GAAU,CAAC;GACrD;AAEF,IAAG,2FAA2F;AAS5F,GAAA,GAAA,YAAA,cADe,MAAM;GAJnB,OAAO;GACP,OAAO;GACP,UAAU;GAEY,CACL,CAAC,CAAC,eAElB;GACH;EACF"}
package/dist/index.d.mts CHANGED
@@ -1,15 +1,16 @@
1
+ import { t as Capabilities_d_exports } from "./capabilities/Capabilities.mjs";
1
2
  import { n as AiError_d_exports } from "./AiError-CAX_48RU.mjs";
2
3
  import { a as Media_d_exports } from "./Media-D_CpcM1Z.mjs";
3
- import { o as Audio_d_exports } from "./Audio-BfCTGnH3.mjs";
4
+ import { o as Audio_d_exports } from "./Audio-DPlTsNdz.mjs";
4
5
  import { o as Image_d_exports } from "./Image-HNmMpMTh.mjs";
5
- import { u as Items_d_exports } from "./Items-pXR5BAgW.mjs";
6
+ import { u as Items_d_exports } from "./Items-D8UaXQx_.mjs";
6
7
  import { t as Music_d_exports } from "./domain/Music.mjs";
7
8
  import { t as Transcript_d_exports } from "./domain/Transcript.mjs";
8
9
  import { a as StructuredFormat_d_exports } from "./StructuredFormat-BbN4dosH.mjs";
9
10
  import { t as Turn_d_exports } from "./domain/Turn.mjs";
10
11
  import { t as Embedding_d_exports } from "./embedding-model/Embedding.mjs";
11
12
  import { t as EmbeddingModel_d_exports } from "./embedding-model/EmbeddingModel.mjs";
12
- import { l as Tool_d_exports } from "./Tool-DP-AwKOf.mjs";
13
+ import { l as Tool_d_exports } from "./Tool-CiFXYjmR.mjs";
13
14
  import { t as LanguageModel_d_exports } from "./language-model/LanguageModel.mjs";
14
15
  import { t as MusicGenerator_d_exports } from "./music-generator/MusicGenerator.mjs";
15
16
  import { t as Memory_d_exports } from "./sandbox/Memory.mjs";
@@ -31,4 +32,4 @@ import { t as JSONL_d_exports } from "./streaming/JSONL.mjs";
31
32
  import { t as Lines_d_exports } from "./streaming/Lines.mjs";
32
33
  import { t as SSE_d_exports } from "./streaming/SSE.mjs";
33
34
  import { t as Metrics_d_exports } from "./observability/Metrics.mjs";
34
- export { AiError_d_exports as AiError, Approval_d_exports as Approval, 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, Memory_d_exports as Memory, Metrics_d_exports as Metrics, Music_d_exports as Music, MusicGenerator_d_exports as MusicGenerator, Retry_d_exports as Retry, SSE_d_exports as SSE, Sandbox_d_exports as Sandbox, SandboxError_d_exports as SandboxError, SandboxImage_d_exports as SandboxImage, SandboxNetwork_d_exports as SandboxNetwork, SpeechSynthesizer_d_exports as SpeechSynthesizer, StructuredFormat_d_exports as StructuredFormat, Tool_d_exports as Tool, ToolEvent_d_exports as ToolEvent, ToolResult_d_exports as ToolResult, 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 };
35
+ export { AiError_d_exports as AiError, Approval_d_exports as Approval, Audio_d_exports as Audio, Capabilities_d_exports as Capabilities, 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, Memory_d_exports as Memory, Metrics_d_exports as Metrics, Music_d_exports as Music, MusicGenerator_d_exports as MusicGenerator, Retry_d_exports as Retry, SSE_d_exports as SSE, Sandbox_d_exports as Sandbox, SandboxError_d_exports as SandboxError, SandboxImage_d_exports as SandboxImage, SandboxNetwork_d_exports as SandboxNetwork, SpeechSynthesizer_d_exports as SpeechSynthesizer, StructuredFormat_d_exports as StructuredFormat, Tool_d_exports as Tool, ToolEvent_d_exports as ToolEvent, ToolResult_d_exports as ToolResult, 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,5 +1,6 @@
1
1
  import { t as AiError_exports } from "./domain/AiError.mjs";
2
2
  import { t as Audio_exports } from "./domain/Audio.mjs";
3
+ import { t as Capabilities_exports } from "./capabilities/Capabilities.mjs";
3
4
  import { t as Image_exports } from "./domain/Image.mjs";
4
5
  import { t as Items_exports } from "./domain/Items.mjs";
5
6
  import { t as Media_exports } from "./domain/Media.mjs";
@@ -31,4 +32,4 @@ import { t as JSONL_exports } from "./streaming/JSONL.mjs";
31
32
  import { t as Lines_exports } from "./streaming/Lines.mjs";
32
33
  import { t as SSE_exports } from "./streaming/SSE.mjs";
33
34
  import { t as Metrics_exports } from "./observability/Metrics.mjs";
34
- export { AiError_exports as AiError, Approval_exports as Approval, 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, Memory_exports as Memory, Metrics_exports as Metrics, Music_exports as Music, MusicGenerator_exports as MusicGenerator, Retry_exports as Retry, SSE_exports as SSE, Sandbox_exports as Sandbox, SandboxError_exports as SandboxError, SandboxImage_exports as SandboxImage, SandboxNetwork_exports as SandboxNetwork, SpeechSynthesizer_exports as SpeechSynthesizer, StructuredFormat_exports as StructuredFormat, Tool_exports as Tool, ToolEvent_exports as ToolEvent, ToolResult_exports as ToolResult, Toolkit_exports as Toolkit, Transcriber_exports as Transcriber, Transcript_exports as Transcript, Turn_exports as Turn, Vector_exports as Vector };
35
+ export { AiError_exports as AiError, Approval_exports as Approval, Audio_exports as Audio, Capabilities_exports as Capabilities, 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, Memory_exports as Memory, Metrics_exports as Metrics, Music_exports as Music, MusicGenerator_exports as MusicGenerator, Retry_exports as Retry, SSE_exports as SSE, Sandbox_exports as Sandbox, SandboxError_exports as SandboxError, SandboxImage_exports as SandboxImage, SandboxNetwork_exports as SandboxNetwork, SpeechSynthesizer_exports as SpeechSynthesizer, StructuredFormat_exports as StructuredFormat, Tool_exports as Tool, ToolEvent_exports as ToolEvent, ToolResult_exports as ToolResult, 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
1
  import { t as AiError } from "../AiError-CAX_48RU.mjs";
2
- import { o as HistoryItem } from "../Items-pXR5BAgW.mjs";
2
+ import { o as HistoryItem } from "../Items-D8UaXQx_.mjs";
3
3
  import { i as StructuredFormat } from "../StructuredFormat-BbN4dosH.mjs";
4
4
  import { Turn, TurnEvent } from "../domain/Turn.mjs";
5
- import { o as ToolDescriptor } from "../Tool-DP-AwKOf.mjs";
5
+ import { o as ToolDescriptor } from "../Tool-CiFXYjmR.mjs";
6
6
  import { Context, Effect, Stream } from "effect";
7
7
 
8
8
  //#region src/language-model/LanguageModel.d.ts