@effect-uai/google 0.12.0 → 0.13.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 (61) hide show
  1. package/dist/Gemini.d.mts +0 -2
  2. package/dist/Gemini.d.mts.map +1 -1
  3. package/dist/Gemini.mjs +1 -1
  4. package/dist/Gemini.mjs.map +1 -1
  5. package/dist/GeminiEmbedding.d.mts +2 -3
  6. package/dist/GeminiEmbedding.d.mts.map +1 -1
  7. package/dist/GeminiEmbedding.mjs +1 -1
  8. package/dist/GeminiEmbedding.mjs.map +1 -1
  9. package/dist/GeminiSynthesizer.d.mts +1 -3
  10. package/dist/GeminiSynthesizer.d.mts.map +1 -1
  11. package/dist/GeminiSynthesizer.mjs +13 -12
  12. package/dist/GeminiSynthesizer.mjs.map +1 -1
  13. package/dist/GeminiSynthesizer.test.d.mts +1 -1
  14. package/dist/GeminiSynthesizer.test.mjs +1 -1
  15. package/dist/GeminiSynthesizer.test.mjs.map +1 -1
  16. package/dist/GeminiTools.d.mts +0 -2
  17. package/dist/GeminiTools.d.mts.map +1 -1
  18. package/dist/GeminiTools.mjs +1 -1
  19. package/dist/GeminiTools.mjs.map +1 -1
  20. package/dist/GoogleDeepResearch.d.mts +2 -3
  21. package/dist/GoogleDeepResearch.d.mts.map +1 -1
  22. package/dist/GoogleDeepResearch.mjs +8 -5
  23. package/dist/GoogleDeepResearch.mjs.map +1 -1
  24. package/dist/GoogleDeepResearch.test.d.mts +1 -1
  25. package/dist/GoogleDeepResearch.test.mjs +1 -1
  26. package/dist/GoogleDeepResearch.test.mjs.map +1 -1
  27. package/dist/LyriaGenerator.d.mts +0 -2
  28. package/dist/LyriaGenerator.d.mts.map +1 -1
  29. package/dist/LyriaGenerator.mjs +9 -6
  30. package/dist/LyriaGenerator.mjs.map +1 -1
  31. package/dist/LyriaGenerator.test.d.mts +1 -1
  32. package/dist/LyriaGenerator.test.mjs +153 -8
  33. package/dist/LyriaGenerator.test.mjs.map +1 -1
  34. package/dist/codec.d.mts +14 -9
  35. package/dist/codec.d.mts.map +1 -1
  36. package/dist/codec.mjs +2 -2
  37. package/dist/codec.mjs.map +1 -1
  38. package/dist/geminiSpeechCodec.d.mts +0 -1
  39. package/dist/geminiSpeechCodec.d.mts.map +1 -1
  40. package/dist/geminiSpeechCodec.mjs.map +1 -1
  41. package/dist/geminiSpeechCodec.test.d.mts +1 -1
  42. package/dist/geminiSpeechCodec.test.mjs +1 -1
  43. package/dist/geminiSpeechCodec.test.mjs.map +1 -1
  44. package/dist/geminiTools.test.d.mts +1 -1
  45. package/dist/geminiTools.test.mjs +17 -11
  46. package/dist/geminiTools.test.mjs.map +1 -1
  47. package/dist/{magic-string.es-CaWgF-3p.mjs → magic-string.es-CUAnjKYC.mjs} +14 -13
  48. package/dist/{magic-string.es-CaWgF-3p.mjs.map → magic-string.es-CUAnjKYC.mjs.map} +1 -1
  49. package/dist/models.d.mts.map +1 -1
  50. package/dist/{dist-CWoAuwS9.mjs → test.DNmyFkvJ-N3QqMRwZ.mjs} +257 -381
  51. package/dist/test.DNmyFkvJ-N3QqMRwZ.mjs.map +1 -0
  52. package/package.json +5 -5
  53. package/src/Gemini.ts +4 -7
  54. package/src/GeminiEmbedding.ts +36 -48
  55. package/src/GeminiSynthesizer.ts +20 -27
  56. package/src/GeminiTools.ts +4 -6
  57. package/src/GoogleDeepResearch.ts +12 -21
  58. package/src/LyriaGenerator.ts +19 -23
  59. package/src/codec.ts +9 -11
  60. package/dist/dist-CWoAuwS9.mjs.map +0 -1
  61. /package/dist/{chunk-uyGKjUfl.mjs → rolldown-runtime-EAsCxrDo.mjs} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@effect-uai/google",
3
- "version": "0.12.0",
3
+ "version": "0.13.0",
4
4
  "description": "Google Gemini provider for @effect-uai/core.",
5
5
  "keywords": [
6
6
  "ai",
@@ -59,13 +59,13 @@
59
59
  "access": "public"
60
60
  },
61
61
  "devDependencies": {
62
- "effect": "4.0.0-beta.94",
63
- "typescript": "^6.0.3",
64
- "@effect-uai/core": "0.12.0"
62
+ "effect": "4.0.0-rc.111",
63
+ "typescript": "^7.0.2",
64
+ "@effect-uai/core": "0.13.0"
65
65
  },
66
66
  "peerDependencies": {
67
67
  "@effect-uai/core": ">=0.2.0 <1",
68
- "effect": ">=4.0.0-beta.94 <5.0.0"
68
+ "effect": ">=4.0.0-rc.111 <5.0.0"
69
69
  },
70
70
  "scripts": {
71
71
  "build": "tsdown",
package/src/Gemini.ts CHANGED
@@ -330,13 +330,10 @@ export const layer = (
330
330
  const typed = Layer.effect(Gemini, make(cfg))
331
331
  const generic = Layer.effect(
332
332
  LanguageModel,
333
- Effect.map(
334
- make(cfg),
335
- (s): LanguageModelService => ({
336
- streamTurn: (request) => s.streamTurn(request as GeminiRequest),
337
- turn: (request) => s.turn(request as GeminiRequest),
338
- }),
339
- ),
333
+ Effect.map(make(cfg), (s): LanguageModelService => ({
334
+ streamTurn: (request) => s.streamTurn(request as GeminiRequest),
335
+ turn: (request) => s.turn(request as GeminiRequest),
336
+ })),
340
337
  )
341
338
  return Layer.merge(typed, generic)
342
339
  }
@@ -121,21 +121,16 @@ const urlRejected = (param: string): AiError.AiError =>
121
121
  */
122
122
  const imageSourceToPart = (param: string) =>
123
123
  Match.type<ImageSource>().pipe(
124
- Match.tag(
125
- "base64",
126
- (s): Effect.Effect<WirePart, AiError.AiError> =>
127
- Effect.succeed({ inlineData: { mimeType: s.mimeType, data: s.base64 } }),
124
+ Match.tag("base64", (s): Effect.Effect<WirePart, AiError.AiError> =>
125
+ Effect.succeed({ inlineData: { mimeType: s.mimeType, data: s.base64 } }),
128
126
  ),
129
- Match.tag(
130
- "bytes",
131
- (s): Effect.Effect<WirePart, AiError.AiError> =>
132
- Effect.succeed({
133
- inlineData: { mimeType: s.mimeType, data: Encoding.encodeBase64(s.bytes) },
134
- }),
127
+ Match.tag("bytes", (s): Effect.Effect<WirePart, AiError.AiError> =>
128
+ Effect.succeed({
129
+ inlineData: { mimeType: s.mimeType, data: Encoding.encodeBase64(s.bytes) },
130
+ }),
135
131
  ),
136
- Match.tag(
137
- "url",
138
- (): Effect.Effect<WirePart, AiError.AiError> => Effect.fail(urlRejected(param)),
132
+ Match.tag("url", (): Effect.Effect<WirePart, AiError.AiError> =>
133
+ Effect.fail(urlRejected(param)),
139
134
  ),
140
135
  Match.exhaustive,
141
136
  )
@@ -291,12 +286,10 @@ const embedImpl =
291
286
  postJson(cfg, `${baseUrl(cfg)}/models/${request.model}:embedContent`, body),
292
287
  ),
293
288
  Effect.flatMap(decodeSingle),
294
- Effect.map(
295
- (decoded): EmbedResponse => ({
296
- embedding: valuesToEmbedding(decoded.embedding.values),
297
- usage: emptyUsage,
298
- }),
299
- ),
289
+ Effect.map((decoded): EmbedResponse => ({
290
+ embedding: valuesToEmbedding(decoded.embedding.values),
291
+ usage: emptyUsage,
292
+ })),
300
293
  )
301
294
 
302
295
  const embedManyImpl =
@@ -309,12 +302,10 @@ const embedManyImpl =
309
302
  postJson(cfg, `${baseUrl(cfg)}/models/${request.model}:batchEmbedContents`, body),
310
303
  ),
311
304
  Effect.flatMap(decodeBatch),
312
- Effect.map(
313
- (decoded): EmbedManyResponse => ({
314
- embeddings: decoded.embeddings.map((e) => valuesToEmbedding(e.values)),
315
- usage: emptyUsage,
316
- }),
317
- ),
305
+ Effect.map((decoded): EmbedManyResponse => ({
306
+ embeddings: decoded.embeddings.map((e) => valuesToEmbedding(e.values)),
307
+ usage: emptyUsage,
308
+ })),
318
309
  )
319
310
 
320
311
  // ---------------------------------------------------------------------------
@@ -346,29 +337,26 @@ export const layer = (
346
337
  const typed = Layer.effect(GeminiEmbedding, make(cfg))
347
338
  const generic = Layer.effect(
348
339
  EmbeddingModel,
349
- Effect.map(
350
- make(cfg),
351
- (s): EmbeddingModelService => ({
352
- // Gemini's embed endpoints emit float32 only. Reject a non-float32
353
- // `encoding` (bucket 1) so a float32 vector isn't handed back
354
- // mislabeled as the requested type. `task` is left silent: it's a
355
- // per-model gap (honored by gemini-embedding-001, ignored by
356
- // gemini-embedding-2 server-side), and per capabilities.md §2.3 we
357
- // don't maintain per-model tables; there's no wire error to translate.
358
- embed: <E extends EmbedEncoding | undefined = undefined>(
359
- req: Omit<CommonEmbedRequest, "encoding"> & { readonly encoding?: E },
360
- ) =>
361
- assertEncoding(req.encoding, ["float32"], "gemini").pipe(
362
- Effect.andThen(s.embed(req as GeminiEmbedRequest)),
363
- ) as Effect.Effect<EmbedResponse<E>, AiError.AiError>,
364
- embedMany: <E extends EmbedEncoding | undefined = undefined>(
365
- req: Omit<CommonEmbedManyRequest, "encoding"> & { readonly encoding?: E },
366
- ) =>
367
- assertEncoding(req.encoding, ["float32"], "gemini").pipe(
368
- Effect.andThen(s.embedMany(req as GeminiEmbedManyRequest)),
369
- ) as Effect.Effect<EmbedManyResponse<E>, AiError.AiError>,
370
- }),
371
- ),
340
+ Effect.map(make(cfg), (s): EmbeddingModelService => ({
341
+ // Gemini's embed endpoints emit float32 only. Reject a non-float32
342
+ // `encoding` (bucket 1) so a float32 vector isn't handed back
343
+ // mislabeled as the requested type. `task` is left silent: it's a
344
+ // per-model gap (honored by gemini-embedding-001, ignored by
345
+ // gemini-embedding-2 server-side), and per capabilities.md §2.3 we
346
+ // don't maintain per-model tables; there's no wire error to translate.
347
+ embed: <E extends EmbedEncoding | undefined = undefined>(
348
+ req: Omit<CommonEmbedRequest, "encoding"> & { readonly encoding?: E },
349
+ ) =>
350
+ assertEncoding(req.encoding, ["float32"], "gemini").pipe(
351
+ Effect.andThen(s.embed(req as GeminiEmbedRequest)),
352
+ ) as Effect.Effect<EmbedResponse<E>, AiError.AiError>,
353
+ embedMany: <E extends EmbedEncoding | undefined = undefined>(
354
+ req: Omit<CommonEmbedManyRequest, "encoding"> & { readonly encoding?: E },
355
+ ) =>
356
+ assertEncoding(req.encoding, ["float32"], "gemini").pipe(
357
+ Effect.andThen(s.embedMany(req as GeminiEmbedManyRequest)),
358
+ ) as Effect.Effect<EmbedManyResponse<E>, AiError.AiError>,
359
+ })),
372
360
  )
373
361
  return Layer.merge(typed, generic)
374
362
  }
@@ -222,21 +222,18 @@ const unsupportedStreamDialogue: SpeechSynthesizerService["streamSynthesizeDialo
222
222
  // ---------------------------------------------------------------------------
223
223
 
224
224
  export const make = (cfg: Config) =>
225
- Effect.map(
226
- HttpClient.HttpClient,
227
- (client): GeminiSynthesizerService => ({
228
- synthesize: (r) =>
229
- synthesizeImpl(cfg)(r).pipe(Effect.provideService(HttpClient.HttpClient, client)),
230
- streamSynthesis: (r) =>
231
- Stream.fromEffect(synthesizeImpl(cfg)(r)).pipe(
232
- Stream.map((b): AudioChunk => ({ bytes: b.bytes })),
233
- Stream.provideService(HttpClient.HttpClient, client),
234
- ),
235
- streamSynthesisFrom: unsupportedStreamFrom,
236
- synthesizeDialogue: unsupportedDialogue,
237
- streamSynthesizeDialogue: unsupportedStreamDialogue,
238
- }),
239
- )
225
+ Effect.map(HttpClient.HttpClient, (client): GeminiSynthesizerService => ({
226
+ synthesize: (r) =>
227
+ synthesizeImpl(cfg)(r).pipe(Effect.provideService(HttpClient.HttpClient, client)),
228
+ streamSynthesis: (r) =>
229
+ Stream.fromEffect(synthesizeImpl(cfg)(r)).pipe(
230
+ Stream.map((b): AudioChunk => ({ bytes: b.bytes })),
231
+ Stream.provideService(HttpClient.HttpClient, client),
232
+ ),
233
+ streamSynthesisFrom: unsupportedStreamFrom,
234
+ synthesizeDialogue: unsupportedDialogue,
235
+ streamSynthesizeDialogue: unsupportedStreamDialogue,
236
+ }))
240
237
 
241
238
  /**
242
239
  * Layer registers both `GeminiSynthesizer` and the generic
@@ -249,17 +246,13 @@ export const layer = (cfg: Config) =>
249
246
  Layer.effect(GeminiSynthesizer, make(cfg)),
250
247
  Layer.effect(
251
248
  SpeechSynthesizer,
252
- Effect.map(
253
- make(cfg),
254
- (s): SpeechSynthesizerService => ({
255
- synthesize: (req: CommonSynthesizeRequest) =>
256
- s.synthesize(req as GeminiSynthesizeRequest),
257
- streamSynthesis: (req: CommonSynthesizeRequest) =>
258
- s.streamSynthesis(req as GeminiSynthesizeRequest),
259
- streamSynthesisFrom: s.streamSynthesisFrom,
260
- synthesizeDialogue: s.synthesizeDialogue,
261
- streamSynthesizeDialogue: s.streamSynthesizeDialogue,
262
- }),
263
- ),
249
+ Effect.map(make(cfg), (s): SpeechSynthesizerService => ({
250
+ synthesize: (req: CommonSynthesizeRequest) => s.synthesize(req as GeminiSynthesizeRequest),
251
+ streamSynthesis: (req: CommonSynthesizeRequest) =>
252
+ s.streamSynthesis(req as GeminiSynthesizeRequest),
253
+ streamSynthesisFrom: s.streamSynthesisFrom,
254
+ synthesizeDialogue: s.synthesizeDialogue,
255
+ streamSynthesizeDialogue: s.streamSynthesizeDialogue,
256
+ })),
264
257
  ),
265
258
  )
@@ -77,12 +77,10 @@ const renderOne = (
77
77
  })
78
78
  : decodeConfig(tool.config).pipe(
79
79
  Result.map(configToWire),
80
- Result.mapError(
81
- (): ToolRenderError => ({
82
- capability: "providerTool",
83
- reason: `unrecognized Gemini provider tool config on "${tool.name}"`,
84
- }),
85
- ),
80
+ Result.mapError((): ToolRenderError => ({
81
+ capability: "providerTool",
82
+ reason: `unrecognized Gemini provider tool config on "${tool.name}"`,
83
+ })),
86
84
  )
87
85
 
88
86
  /**
@@ -217,27 +217,18 @@ const turnFromInteraction = (wire: WireInteraction): Turn => {
217
217
  export const jobStateOf = (wire: WireInteraction): ResearchState =>
218
218
  Match.value(wire.status ?? "").pipe(
219
219
  Match.whenOr("queued", "pending", (): ResearchState => ({ _tag: "Pending" })),
220
- Match.whenOr(
221
- "in_progress",
222
- "running",
223
- "processing",
224
- (): ResearchState => ({ _tag: "Running" }),
225
- ),
226
- Match.whenOr(
227
- "completed",
228
- "succeeded",
229
- (): ResearchState => ({ _tag: "Succeeded", result: turnFromInteraction(wire) }),
230
- ),
231
- Match.whenOr(
232
- "failed",
233
- "error",
234
- "cancelled",
235
- (): ResearchState => ({
236
- _tag: "Failed",
237
- ...(wire.error?.message != null && { reason: wire.error.message }),
238
- raw: wire,
239
- }),
240
- ),
220
+ Match.whenOr("in_progress", "running", "processing", (): ResearchState => ({
221
+ _tag: "Running",
222
+ })),
223
+ Match.whenOr("completed", "succeeded", (): ResearchState => ({
224
+ _tag: "Succeeded",
225
+ result: turnFromInteraction(wire),
226
+ })),
227
+ Match.whenOr("failed", "error", "cancelled", (): ResearchState => ({
228
+ _tag: "Failed",
229
+ ...(wire.error?.message != null && { reason: wire.error.message }),
230
+ raw: wire,
231
+ })),
241
232
  Match.orElse((): ResearchState => ({ _tag: "Running" })),
242
233
  )
243
234
 
@@ -105,19 +105,18 @@ const isClipModel = (model: string): boolean => model.includes("clip")
105
105
 
106
106
  export const realizedFormat: (mime: LyriaResponseMimeType) => AudioFormat =
107
107
  Match.type<LyriaResponseMimeType>().pipe(
108
- Match.when(
109
- "audio/mp3",
110
- (): AudioFormat => ({ container: "mp3", encoding: "mp3", sampleRate: 44100, channels: 2 }),
111
- ),
112
- Match.when(
113
- "audio/wav",
114
- (): AudioFormat => ({
115
- container: "wav",
116
- encoding: "pcm_s16le",
117
- sampleRate: 44100,
118
- channels: 2,
119
- }),
120
- ),
108
+ Match.when("audio/mp3", (): AudioFormat => ({
109
+ container: "mp3",
110
+ encoding: "mp3",
111
+ sampleRate: 44100,
112
+ channels: 2,
113
+ })),
114
+ Match.when("audio/wav", (): AudioFormat => ({
115
+ container: "wav",
116
+ encoding: "pcm_s16le",
117
+ sampleRate: 44100,
118
+ channels: 2,
119
+ })),
121
120
  Match.exhaustive,
122
121
  )
123
122
 
@@ -395,15 +394,12 @@ export const layer = (
395
394
  Layer.effect(LyriaGenerator, make(cfg)),
396
395
  Layer.effect(
397
396
  MusicGenerator,
398
- Effect.map(
399
- make(cfg),
400
- (s): MusicGeneratorService => ({
401
- generate: (req: CommonGenerateMusicRequest) =>
402
- s.generate({ ...req, model: req.model as LyriaModel }),
403
- streamGeneration: (req: CommonStreamGenerateMusicRequest) =>
404
- s.streamGeneration({ ...req, model: req.model as LyriaModel }),
405
- streamGenerationFrom: s.streamGenerationFrom,
406
- }),
407
- ),
397
+ Effect.map(make(cfg), (s): MusicGeneratorService => ({
398
+ generate: (req: CommonGenerateMusicRequest) =>
399
+ s.generate({ ...req, model: req.model as LyriaModel }),
400
+ streamGeneration: (req: CommonStreamGenerateMusicRequest) =>
401
+ s.streamGeneration({ ...req, model: req.model as LyriaModel }),
402
+ streamGenerationFrom: s.streamGenerationFrom,
403
+ })),
408
404
  ),
409
405
  )
package/src/codec.ts CHANGED
@@ -218,16 +218,12 @@ const messageText = (message: Message): string => message.content.map(blockText)
218
218
  */
219
219
  const imageSourceToParts = Match.type<InputImage["source"]>().pipe(
220
220
  Match.tag("url", (): ReadonlyArray<RequestPart> => []),
221
- Match.tag(
222
- "base64",
223
- (s): ReadonlyArray<RequestPart> => [{ inlineData: { mimeType: s.mimeType, data: s.base64 } }],
224
- ),
225
- Match.tag(
226
- "bytes",
227
- (s): ReadonlyArray<RequestPart> => [
228
- { inlineData: { mimeType: s.mimeType, data: Encoding.encodeBase64(s.bytes) } },
229
- ],
230
- ),
221
+ Match.tag("base64", (s): ReadonlyArray<RequestPart> => [
222
+ { inlineData: { mimeType: s.mimeType, data: s.base64 } },
223
+ ]),
224
+ Match.tag("bytes", (s): ReadonlyArray<RequestPart> => [
225
+ { inlineData: { mimeType: s.mimeType, data: Encoding.encodeBase64(s.bytes) } },
226
+ ]),
231
227
  Match.exhaustive,
232
228
  )
233
229
 
@@ -434,7 +430,9 @@ const sanitizeSchema = (schema: unknown): unknown => {
434
430
  )
435
431
  }
436
432
 
437
- const toolDescriptorsToTools = (tools: ReadonlyArray<ToolDescriptor>): ReadonlyArray<RequestTool> =>
433
+ const toolDescriptorsToTools = (
434
+ tools: ReadonlyArray<ToolDescriptor>,
435
+ ): ReadonlyArray<RequestTool> =>
438
436
  tools.length === 0
439
437
  ? []
440
438
  : [