effect 4.0.0-beta.33 → 4.0.0-beta.34

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 (99) hide show
  1. package/dist/Effect.d.ts +5 -3
  2. package/dist/Effect.d.ts.map +1 -1
  3. package/dist/Effect.js +4 -4
  4. package/dist/Effect.js.map +1 -1
  5. package/dist/FileSystem.d.ts.map +1 -1
  6. package/dist/FileSystem.js +2 -1
  7. package/dist/FileSystem.js.map +1 -1
  8. package/dist/Graph.d.ts.map +1 -1
  9. package/dist/Graph.js +2 -1
  10. package/dist/Graph.js.map +1 -1
  11. package/dist/MutableHashMap.d.ts +7 -0
  12. package/dist/MutableHashMap.d.ts.map +1 -1
  13. package/dist/MutableHashMap.js +8 -0
  14. package/dist/MutableHashMap.js.map +1 -1
  15. package/dist/MutableHashSet.d.ts +7 -0
  16. package/dist/MutableHashSet.d.ts.map +1 -1
  17. package/dist/MutableHashSet.js +8 -0
  18. package/dist/MutableHashSet.js.map +1 -1
  19. package/dist/Resource.d.ts.map +1 -1
  20. package/dist/Resource.js +2 -1
  21. package/dist/Resource.js.map +1 -1
  22. package/dist/SubscriptionRef.d.ts.map +1 -1
  23. package/dist/SubscriptionRef.js +2 -1
  24. package/dist/SubscriptionRef.js.map +1 -1
  25. package/dist/TxDeferred.d.ts.map +1 -1
  26. package/dist/TxDeferred.js +2 -1
  27. package/dist/TxDeferred.js.map +1 -1
  28. package/dist/TxHashMap.d.ts.map +1 -1
  29. package/dist/TxHashMap.js +2 -1
  30. package/dist/TxHashMap.js.map +1 -1
  31. package/dist/TxHashSet.d.ts +1 -1
  32. package/dist/TxHashSet.d.ts.map +1 -1
  33. package/dist/TxHashSet.js +2 -1
  34. package/dist/TxHashSet.js.map +1 -1
  35. package/dist/TxPriorityQueue.d.ts +1 -1
  36. package/dist/TxPriorityQueue.d.ts.map +1 -1
  37. package/dist/TxPriorityQueue.js +2 -1
  38. package/dist/TxPriorityQueue.js.map +1 -1
  39. package/dist/TxSemaphore.d.ts.map +1 -1
  40. package/dist/TxSemaphore.js +2 -1
  41. package/dist/TxSemaphore.js.map +1 -1
  42. package/dist/internal/effect.js +1 -1
  43. package/dist/internal/effect.js.map +1 -1
  44. package/dist/unstable/ai/AiError.d.ts +1 -3
  45. package/dist/unstable/ai/AiError.d.ts.map +1 -1
  46. package/dist/unstable/ai/AiError.js +1 -3
  47. package/dist/unstable/ai/AiError.js.map +1 -1
  48. package/dist/unstable/ai/EmbeddingModel.d.ts +130 -0
  49. package/dist/unstable/ai/EmbeddingModel.d.ts.map +1 -0
  50. package/dist/unstable/ai/EmbeddingModel.js +127 -0
  51. package/dist/unstable/ai/EmbeddingModel.js.map +1 -0
  52. package/dist/unstable/ai/LanguageModel.d.ts.map +1 -1
  53. package/dist/unstable/ai/LanguageModel.js +18 -8
  54. package/dist/unstable/ai/LanguageModel.js.map +1 -1
  55. package/dist/unstable/ai/ResponseIdTracker.js +3 -3
  56. package/dist/unstable/ai/ResponseIdTracker.js.map +1 -1
  57. package/dist/unstable/ai/Tool.d.ts +1 -1
  58. package/dist/unstable/ai/Tool.d.ts.map +1 -1
  59. package/dist/unstable/ai/Tool.js +1 -1
  60. package/dist/unstable/ai/Tool.js.map +1 -1
  61. package/dist/unstable/ai/index.d.ts +17 -0
  62. package/dist/unstable/ai/index.d.ts.map +1 -1
  63. package/dist/unstable/ai/index.js +17 -0
  64. package/dist/unstable/ai/index.js.map +1 -1
  65. package/dist/unstable/http/Url.d.ts +604 -0
  66. package/dist/unstable/http/Url.d.ts.map +1 -0
  67. package/dist/unstable/http/Url.js +256 -0
  68. package/dist/unstable/http/Url.js.map +1 -0
  69. package/dist/unstable/http/index.d.ts +4 -0
  70. package/dist/unstable/http/index.d.ts.map +1 -1
  71. package/dist/unstable/http/index.js +4 -0
  72. package/dist/unstable/http/index.js.map +1 -1
  73. package/dist/unstable/httpapi/HttpApiMiddleware.d.ts +30 -1
  74. package/dist/unstable/httpapi/HttpApiMiddleware.d.ts.map +1 -1
  75. package/dist/unstable/httpapi/HttpApiMiddleware.js +27 -0
  76. package/dist/unstable/httpapi/HttpApiMiddleware.js.map +1 -1
  77. package/package.json +1 -1
  78. package/src/Effect.ts +7 -6
  79. package/src/FileSystem.ts +2 -1
  80. package/src/Graph.ts +2 -1
  81. package/src/MutableHashMap.ts +9 -0
  82. package/src/MutableHashSet.ts +9 -0
  83. package/src/Resource.ts +2 -1
  84. package/src/SubscriptionRef.ts +2 -1
  85. package/src/TxDeferred.ts +2 -2
  86. package/src/TxHashMap.ts +2 -1
  87. package/src/TxHashSet.ts +2 -2
  88. package/src/TxPriorityQueue.ts +2 -3
  89. package/src/TxSemaphore.ts +2 -1
  90. package/src/internal/effect.ts +11 -4
  91. package/src/unstable/ai/AiError.ts +1 -3
  92. package/src/unstable/ai/EmbeddingModel.ts +209 -0
  93. package/src/unstable/ai/LanguageModel.ts +36 -4
  94. package/src/unstable/ai/ResponseIdTracker.ts +3 -3
  95. package/src/unstable/ai/Tool.ts +2 -2
  96. package/src/unstable/ai/index.ts +18 -0
  97. package/src/unstable/http/Url.ts +650 -0
  98. package/src/unstable/http/index.ts +5 -0
  99. package/src/unstable/httpapi/HttpApiMiddleware.ts +46 -1
package/src/TxHashSet.ts CHANGED
@@ -10,7 +10,7 @@ import type { Inspectable } from "./Inspectable.ts"
10
10
  import { NodeInspectSymbol, toJson } from "./Inspectable.ts"
11
11
  import type { Pipeable } from "./Pipeable.ts"
12
12
  import { pipeArguments } from "./Pipeable.ts"
13
- import type { Predicate, Refinement } from "./Predicate.ts"
13
+ import { hasProperty, type Predicate, type Refinement } from "./Predicate.ts"
14
14
  import * as TxRef from "./TxRef.ts"
15
15
  import type { NoInfer } from "./Types.ts"
16
16
 
@@ -286,7 +286,7 @@ export const fromHashSet = <V>(hashSet: HashSet.HashSet<V>): Effect.Effect<TxHas
286
286
  * @since 2.0.0
287
287
  * @category guards
288
288
  */
289
- export const isTxHashSet = (u: unknown): u is TxHashSet<unknown> => typeof u === "object" && u !== null && TypeId in u
289
+ export const isTxHashSet = (u: unknown): u is TxHashSet<unknown> => hasProperty(u, TypeId)
290
290
 
291
291
  /**
292
292
  * Adds a value to the TxHashSet. If the value already exists, the operation has no effect.
@@ -16,7 +16,7 @@ import * as O from "./Option.ts"
16
16
  import type { Order } from "./Order.ts"
17
17
  import type { Pipeable } from "./Pipeable.ts"
18
18
  import { pipeArguments } from "./Pipeable.ts"
19
- import type { Predicate } from "./Predicate.ts"
19
+ import { hasProperty, type Predicate } from "./Predicate.ts"
20
20
  import * as TxRef from "./TxRef.ts"
21
21
 
22
22
  const TypeId = "~effect/transactions/TxPriorityQueue"
@@ -763,5 +763,4 @@ export const toArray = <A>(self: TxPriorityQueue<A>): Effect.Effect<Array<A>, ne
763
763
  * @since 4.0.0
764
764
  * @category guards
765
765
  */
766
- export const isTxPriorityQueue = (u: unknown): u is TxPriorityQueue<unknown> =>
767
- typeof u === "object" && u !== null && TypeId in u
766
+ export const isTxPriorityQueue = (u: unknown): u is TxPriorityQueue<unknown> => hasProperty(u, TypeId)
@@ -7,6 +7,7 @@ import type { Inspectable } from "./Inspectable.ts"
7
7
  import { NodeInspectSymbol, toJson } from "./Inspectable.ts"
8
8
  import type { Pipeable } from "./Pipeable.ts"
9
9
  import { pipeArguments } from "./Pipeable.ts"
10
+ import { hasProperty } from "./Predicate.ts"
10
11
  import type * as Scope from "./Scope.ts"
11
12
  import * as TxRef from "./TxRef.ts"
12
13
 
@@ -738,4 +739,4 @@ export const withPermitScoped = (self: TxSemaphore): Effect.Effect<void, never,
738
739
  * @since 4.0.0
739
740
  * @category guards
740
741
  */
741
- export const isTxSemaphore = (u: unknown): u is TxSemaphore => typeof u === "object" && u !== null && TypeId in u
742
+ export const isTxSemaphore = (u: unknown): u is TxSemaphore => hasProperty(u, TypeId)
@@ -3794,11 +3794,18 @@ export const scopedWith = <A, E, R>(
3794
3794
  /** @internal */
3795
3795
  export const acquireRelease = <A, E, R>(
3796
3796
  acquire: Effect.Effect<A, E, R>,
3797
- release: (a: A, exit: Exit.Exit<unknown, unknown>) => Effect.Effect<unknown>
3797
+ release: (a: A, exit: Exit.Exit<unknown, unknown>) => Effect.Effect<unknown>,
3798
+ options?: { readonly interruptible?: boolean }
3798
3799
  ): Effect.Effect<A, E, R | Scope.Scope> =>
3799
- uninterruptible(
3800
- flatMap(scope, (scope) =>
3801
- tap(acquire, (a) => scopeAddFinalizerExit(scope, (exit) => internalCall(() => release(a, exit)))))
3800
+ uninterruptibleMask((restore) =>
3801
+ flatMap(
3802
+ scope,
3803
+ (scope) =>
3804
+ tap(
3805
+ options?.interruptible ? restore(acquire) : acquire,
3806
+ (a) => scopeAddFinalizerExit(scope, (exit) => release(a, exit))
3807
+ )
3808
+ )
3802
3809
  )
3803
3810
 
3804
3811
  /** @internal */
@@ -1396,10 +1396,8 @@ export class AiError extends Schema.ErrorClass<AiError>(
1396
1396
  method: Schema.String,
1397
1397
  reason: AiErrorReason
1398
1398
  }) {
1399
- /**
1400
- * @since 1.0.0
1401
- */
1402
1399
  readonly [TypeId] = TypeId
1400
+ override readonly cause = this.reason
1403
1401
 
1404
1402
  /**
1405
1403
  * Delegates to the underlying reason's `isRetryable` getter.
@@ -0,0 +1,209 @@
1
+ /**
2
+ * The `EmbeddingModel` module provides provider-agnostic text embedding capabilities.
3
+ *
4
+ * @example
5
+ * ```ts
6
+ * import { Effect } from "effect"
7
+ * import { EmbeddingModel } from "effect/unstable/ai"
8
+ *
9
+ * const program = Effect.gen(function*() {
10
+ * const model = yield* EmbeddingModel.EmbeddingModel
11
+ * return yield* model.embed("hello world")
12
+ * })
13
+ * ```
14
+ *
15
+ * @since 4.0.0
16
+ */
17
+ import * as Effect from "../../Effect.ts"
18
+ import * as Exit from "../../Exit.ts"
19
+ import * as Request from "../../Request.ts"
20
+ import * as RequestResolver from "../../RequestResolver.ts"
21
+ import * as Schema from "../../Schema.ts"
22
+ import * as ServiceMap from "../../ServiceMap.ts"
23
+ import * as AiError from "./AiError.ts"
24
+
25
+ /**
26
+ * Service tag for embedding model operations.
27
+ *
28
+ * @since 4.0.0
29
+ * @category services
30
+ */
31
+ export class EmbeddingModel extends ServiceMap.Service<EmbeddingModel, Service>()(
32
+ "effect/unstable/ai/EmbeddingModel"
33
+ ) {}
34
+
35
+ /**
36
+ * Service tag that provides the current embedding dimensions.
37
+ *
38
+ * @since 4.0.0
39
+ * @category services
40
+ */
41
+ export class Dimensions extends ServiceMap.Service<Dimensions, number>()(
42
+ "effect/unstable/ai/EmbeddingModel/Dimensions"
43
+ ) {}
44
+
45
+ /**
46
+ * Token usage metadata for embedding operations.
47
+ *
48
+ * @since 4.0.0
49
+ * @category models
50
+ */
51
+ export class EmbeddingUsage extends Schema.Class<EmbeddingUsage>(
52
+ "effect/ai/EmbeddingModel/EmbeddingUsage"
53
+ )({
54
+ inputTokens: Schema.UndefinedOr(Schema.Finite)
55
+ }) {}
56
+
57
+ /**
58
+ * Response for a single embedding request.
59
+ *
60
+ * @since 4.0.0
61
+ * @category models
62
+ */
63
+ export class EmbedResponse extends Schema.Class<EmbedResponse>(
64
+ "effect/ai/EmbeddingModel/EmbedResponse"
65
+ )({
66
+ vector: Schema.Array(Schema.Finite)
67
+ }) {}
68
+
69
+ /**
70
+ * Response for multiple embeddings.
71
+ *
72
+ * @since 4.0.0
73
+ * @category models
74
+ */
75
+ export class EmbedManyResponse extends Schema.Class<EmbedManyResponse>(
76
+ "effect/ai/EmbeddingModel/EmbedManyResponse"
77
+ )({
78
+ embeddings: Schema.Array(EmbedResponse),
79
+ usage: EmbeddingUsage
80
+ }) {}
81
+
82
+ /**
83
+ * Provider input options for embedding requests.
84
+ *
85
+ * @since 4.0.0
86
+ * @category models
87
+ */
88
+ export interface ProviderOptions {
89
+ readonly inputs: ReadonlyArray<string>
90
+ }
91
+
92
+ /**
93
+ * Provider response for batch embedding requests.
94
+ *
95
+ * @since 4.0.0
96
+ * @category models
97
+ */
98
+ export interface ProviderResponse {
99
+ readonly results: Array<Array<number>>
100
+ readonly usage: {
101
+ readonly inputTokens: number | undefined
102
+ }
103
+ }
104
+
105
+ /**
106
+ * Tagged request used by request resolvers for embedding operations.
107
+ *
108
+ * @since 4.0.0
109
+ * @category constructors
110
+ */
111
+ export class EmbeddingRequest extends Request.TaggedClass("EmbeddingRequest")<
112
+ { readonly input: string },
113
+ EmbedResponse,
114
+ AiError.AiError
115
+ > {}
116
+
117
+ /**
118
+ * Service interface for embedding operations.
119
+ *
120
+ * @since 4.0.0
121
+ * @category models
122
+ */
123
+ export interface Service {
124
+ readonly resolver: RequestResolver.RequestResolver<EmbeddingRequest>
125
+ readonly embed: (input: string) => Effect.Effect<EmbedResponse, AiError.AiError>
126
+ readonly embedMany: (input: ReadonlyArray<string>) => Effect.Effect<EmbedManyResponse, AiError.AiError>
127
+ }
128
+
129
+ const invalidProviderResponse = (description: string): AiError.AiError =>
130
+ AiError.make({
131
+ module: "EmbeddingModel",
132
+ method: "embedMany",
133
+ reason: new AiError.InvalidOutputError({ description })
134
+ })
135
+
136
+ /**
137
+ * Creates an EmbeddingModel service from a provider embedMany implementation.
138
+ *
139
+ * @since 4.0.0
140
+ * @category constructors
141
+ */
142
+ export const make: (params: {
143
+ readonly embedMany: (options: ProviderOptions) => Effect.Effect<ProviderResponse, AiError.AiError>
144
+ }) => Effect.Effect<Service> = Effect.fnUntraced(function*(params) {
145
+ const resolver = RequestResolver.make<EmbeddingRequest>((entries) =>
146
+ Effect.flatMap(
147
+ params.embedMany({
148
+ inputs: entries.map((entry) => entry.request.input)
149
+ }),
150
+ (response) =>
151
+ Effect.map(mapProviderResults(entries.length, response.results), (embeddings) => {
152
+ for (let i = 0; i < entries.length; i++) {
153
+ entries[i].completeUnsafe(Exit.succeed(embeddings[i]))
154
+ }
155
+ })
156
+ )
157
+ ).pipe(
158
+ RequestResolver.withSpan("EmbeddingModel.resolver")
159
+ )
160
+
161
+ return EmbeddingModel.of({
162
+ resolver,
163
+ embed: (input) =>
164
+ Effect.request(new EmbeddingRequest({ input }), resolver).pipe(
165
+ Effect.withSpan("EmbeddingModel.embed")
166
+ ),
167
+ embedMany: (input) =>
168
+ (input.length === 0
169
+ ? Effect.succeed(
170
+ new EmbedManyResponse({
171
+ embeddings: [],
172
+ usage: new EmbeddingUsage({ inputTokens: undefined })
173
+ })
174
+ )
175
+ : params.embedMany({ inputs: input }).pipe(
176
+ Effect.flatMap((response) =>
177
+ mapProviderResults(input.length, response.results).pipe(
178
+ Effect.map((embeddings) =>
179
+ new EmbedManyResponse({
180
+ embeddings,
181
+ usage: new EmbeddingUsage({
182
+ inputTokens: response.usage.inputTokens
183
+ })
184
+ })
185
+ )
186
+ )
187
+ )
188
+ )).pipe(Effect.withSpan("EmbeddingModel.embedMany"))
189
+ })
190
+ })
191
+
192
+ const mapProviderResults = (
193
+ inputLength: number,
194
+ results: Array<Array<number>>
195
+ ): Effect.Effect<Array<EmbedResponse>, AiError.AiError> => {
196
+ const embeddings = new Array<EmbedResponse>(inputLength)
197
+ if (results.length !== inputLength) {
198
+ return Effect.fail(
199
+ invalidProviderResponse(
200
+ `Provider returned ${results.length} embeddings but expected ${inputLength}`
201
+ )
202
+ )
203
+ }
204
+ for (let i = 0; i < results.length; i++) {
205
+ const vector = results[i]
206
+ embeddings[i] = new EmbedResponse({ vector })
207
+ }
208
+ return Effect.succeed(embeddings)
209
+ }
@@ -937,6 +937,20 @@ export const make: (params: {
937
937
  const tracker = Option.getOrUndefined(yield* Effect.serviceOption(ResponseIdTracker.ResponseIdTracker))
938
938
  const toolChoice = options.toolChoice ?? "auto"
939
939
 
940
+ const withNonIncrementalFallback = <R>(
941
+ effect: Effect.Effect<Array<Response.PartEncoded>, AiError.AiError, R>
942
+ ): Effect.Effect<Array<Response.PartEncoded>, AiError.AiError, R | IdGenerator> =>
943
+ providerOptions.incrementalPrompt ?
944
+ effect.pipe(
945
+ Effect.catchReason("AiError", "InvalidRequestError", (_) =>
946
+ params.generateText({
947
+ ...providerOptions,
948
+ incrementalPrompt: undefined,
949
+ previousResponseId: undefined
950
+ }))
951
+ ) :
952
+ effect
953
+
940
954
  // Check for pending approvals that need resolution
941
955
  const { approved, denied } = collectToolApprovals(
942
956
  providerOptions.prompt.content,
@@ -968,7 +982,7 @@ export const make: (params: {
968
982
  const ResponseSchema = Schema.mutable(
969
983
  Schema.Array(Response.Part(Toolkit.empty))
970
984
  )
971
- const rawContent = yield* params.generateText(providerOptions)
985
+ const rawContent = yield* withNonIncrementalFallback(params.generateText(providerOptions))
972
986
  const content = yield* Schema.decodeEffect(ResponseSchema)(rawContent)
973
987
  if (tracker) {
974
988
  const responseMetadata = content.find((part) => part.type === "response-metadata")
@@ -1006,7 +1020,7 @@ export const make: (params: {
1006
1020
  const ResponseSchema = Schema.mutable(
1007
1021
  Schema.Array(Response.Part(Toolkit.empty))
1008
1022
  )
1009
- const rawContent = yield* params.generateText(providerOptions)
1023
+ const rawContent = yield* withNonIncrementalFallback(params.generateText(providerOptions))
1010
1024
  const content = yield* Schema.decodeEffect(ResponseSchema)(rawContent)
1011
1025
  if (tracker) {
1012
1026
  const responseMetadata = content.find((part) => part.type === "response-metadata")
@@ -1085,7 +1099,7 @@ export const make: (params: {
1085
1099
  // If tool call resolution is disabled, return the response without
1086
1100
  // resolving the tool calls that were generated
1087
1101
  if (options.disableToolCallResolution === true) {
1088
- const rawContent = yield* params.generateText(providerOptions)
1102
+ const rawContent = yield* withNonIncrementalFallback(params.generateText(providerOptions))
1089
1103
  const content = yield* Schema.decodeEffect(ResponseSchema)(rawContent)
1090
1104
  if (tracker) {
1091
1105
  const responseMetadata = content.find((part) => part.type === "response-metadata")
@@ -1096,7 +1110,7 @@ export const make: (params: {
1096
1110
  return content as Array<Response.Part<Tools>>
1097
1111
  }
1098
1112
 
1099
- const rawContent = yield* params.generateText(providerOptions)
1113
+ const rawContent = yield* withNonIncrementalFallback(params.generateText(providerOptions))
1100
1114
 
1101
1115
  // Resolve the generated tool calls
1102
1116
  const toolResults = yield* resolveToolCalls(
@@ -1154,6 +1168,20 @@ export const make: (params: {
1154
1168
  const tracker = Option.getOrUndefined(yield* Effect.serviceOption(ResponseIdTracker.ResponseIdTracker))
1155
1169
  const toolChoice = options.toolChoice ?? "auto"
1156
1170
 
1171
+ const withNonIncrementalFallback = <R>(
1172
+ stream: Stream.Stream<Response.StreamPartEncoded, AiError.AiError, R>
1173
+ ): Stream.Stream<Response.StreamPartEncoded, AiError.AiError, R | IdGenerator> =>
1174
+ providerOptions.incrementalPrompt ?
1175
+ stream.pipe(
1176
+ Stream.catchReason("AiError", "InvalidRequestError", (_) =>
1177
+ params.streamText({
1178
+ ...providerOptions,
1179
+ incrementalPrompt: undefined,
1180
+ previousResponseId: undefined
1181
+ }))
1182
+ ) :
1183
+ stream
1184
+
1157
1185
  // Check for pending approvals that need resolution
1158
1186
  const { approved: pendingApproved, denied: pendingDenied } = collectToolApprovals(providerOptions.prompt.content, {
1159
1187
  excludeResolved: true
@@ -1185,6 +1213,7 @@ export const make: (params: {
1185
1213
  const decodeParts = Schema.decodeEffect(schema)
1186
1214
  return pipe(
1187
1215
  params.streamText(providerOptions),
1216
+ withNonIncrementalFallback,
1188
1217
  Stream.mapArrayEffect((parts) =>
1189
1218
  decodeParts(parts).pipe(
1190
1219
  tracker ?
@@ -1234,6 +1263,7 @@ export const make: (params: {
1234
1263
  const decodeParts = Schema.decodeEffect(schema)
1235
1264
  return pipe(
1236
1265
  params.streamText(providerOptions),
1266
+ withNonIncrementalFallback,
1237
1267
  Stream.mapArrayEffect((parts) =>
1238
1268
  decodeParts(parts).pipe(
1239
1269
  tracker ?
@@ -1340,6 +1370,7 @@ export const make: (params: {
1340
1370
  const schema = Schema.NonEmptyArray(Response.StreamPart(toolkit))
1341
1371
  const decodeParts = Schema.decodeEffect(schema)
1342
1372
  return params.streamText(providerOptions).pipe(
1373
+ withNonIncrementalFallback,
1343
1374
  Stream.mapArrayEffect((parts) =>
1344
1375
  decodeParts(parts).pipe(
1345
1376
  tracker ?
@@ -1419,6 +1450,7 @@ export const make: (params: {
1419
1450
  })
1420
1451
 
1421
1452
  yield* params.streamText(providerOptions).pipe(
1453
+ withNonIncrementalFallback,
1422
1454
  Stream.runForEachArray(
1423
1455
  Effect.fnUntraced(function*(chunk) {
1424
1456
  const parts = yield* decodeParts(chunk)
@@ -38,16 +38,16 @@ export class ResponseIdTracker
38
38
  * @category constructors
39
39
  */
40
40
  export const make: Effect.Effect<Service> = Effect.sync(() => {
41
- let sentParts = new WeakMap<object, string>()
41
+ const sentParts = new Map<object, string>()
42
42
 
43
43
  const none = () => {
44
- sentParts = new WeakMap<object, string>()
44
+ sentParts.clear()
45
45
  return Option.none<PrepareResult>()
46
46
  }
47
47
 
48
48
  return {
49
49
  clearUnsafe() {
50
- sentParts = new WeakMap<object, string>()
50
+ sentParts.clear()
51
51
  },
52
52
  markParts(parts, responseId) {
53
53
  for (let i = 0; i < parts.length; i++) {
@@ -1149,7 +1149,7 @@ const dynamicProto = <
1149
1149
  */
1150
1150
  export const make = <
1151
1151
  const Name extends string,
1152
- Parameters extends Schema.Top = typeof Schema.Void,
1152
+ Parameters extends Schema.Top = typeof EmptyParams,
1153
1153
  Success extends Schema.Top = typeof Schema.Void,
1154
1154
  Failure extends Schema.Top = typeof Schema.Never,
1155
1155
  Mode extends FailureMode | undefined = undefined,
@@ -1210,7 +1210,7 @@ export const make = <
1210
1210
  return userDefinedProto({
1211
1211
  name,
1212
1212
  description: options?.description,
1213
- parametersSchema: options?.parameters ?? Schema.Void,
1213
+ parametersSchema: options?.parameters ?? EmptyParams,
1214
1214
  successSchema,
1215
1215
  failureSchema,
1216
1216
  failureMode: options?.failureMode ?? "error",
@@ -153,6 +153,24 @@ export * as AnthropicStructuredOutput from "./AnthropicStructuredOutput.ts"
153
153
  */
154
154
  export * as Chat from "./Chat.ts"
155
155
 
156
+ /**
157
+ * The `EmbeddingModel` module provides provider-agnostic text embedding capabilities.
158
+ *
159
+ * @example
160
+ * ```ts
161
+ * import { Effect } from "effect"
162
+ * import { EmbeddingModel } from "effect/unstable/ai"
163
+ *
164
+ * const program = Effect.gen(function*() {
165
+ * const model = yield* EmbeddingModel.EmbeddingModel
166
+ * return yield* model.embed("hello world")
167
+ * })
168
+ * ```
169
+ *
170
+ * @since 4.0.0
171
+ */
172
+ export * as EmbeddingModel from "./EmbeddingModel.ts"
173
+
156
174
  /**
157
175
  * The `IdGenerator` module provides a pluggable system for generating unique identifiers
158
176
  * for tool calls and other items in the Effect AI SDKs.