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.
- package/dist/Effect.d.ts +5 -3
- package/dist/Effect.d.ts.map +1 -1
- package/dist/Effect.js +4 -4
- package/dist/Effect.js.map +1 -1
- package/dist/FileSystem.d.ts.map +1 -1
- package/dist/FileSystem.js +2 -1
- package/dist/FileSystem.js.map +1 -1
- package/dist/Graph.d.ts.map +1 -1
- package/dist/Graph.js +2 -1
- package/dist/Graph.js.map +1 -1
- package/dist/MutableHashMap.d.ts +7 -0
- package/dist/MutableHashMap.d.ts.map +1 -1
- package/dist/MutableHashMap.js +8 -0
- package/dist/MutableHashMap.js.map +1 -1
- package/dist/MutableHashSet.d.ts +7 -0
- package/dist/MutableHashSet.d.ts.map +1 -1
- package/dist/MutableHashSet.js +8 -0
- package/dist/MutableHashSet.js.map +1 -1
- package/dist/Resource.d.ts.map +1 -1
- package/dist/Resource.js +2 -1
- package/dist/Resource.js.map +1 -1
- package/dist/SubscriptionRef.d.ts.map +1 -1
- package/dist/SubscriptionRef.js +2 -1
- package/dist/SubscriptionRef.js.map +1 -1
- package/dist/TxDeferred.d.ts.map +1 -1
- package/dist/TxDeferred.js +2 -1
- package/dist/TxDeferred.js.map +1 -1
- package/dist/TxHashMap.d.ts.map +1 -1
- package/dist/TxHashMap.js +2 -1
- package/dist/TxHashMap.js.map +1 -1
- package/dist/TxHashSet.d.ts +1 -1
- package/dist/TxHashSet.d.ts.map +1 -1
- package/dist/TxHashSet.js +2 -1
- package/dist/TxHashSet.js.map +1 -1
- package/dist/TxPriorityQueue.d.ts +1 -1
- package/dist/TxPriorityQueue.d.ts.map +1 -1
- package/dist/TxPriorityQueue.js +2 -1
- package/dist/TxPriorityQueue.js.map +1 -1
- package/dist/TxSemaphore.d.ts.map +1 -1
- package/dist/TxSemaphore.js +2 -1
- package/dist/TxSemaphore.js.map +1 -1
- package/dist/internal/effect.js +1 -1
- package/dist/internal/effect.js.map +1 -1
- package/dist/unstable/ai/AiError.d.ts +1 -3
- package/dist/unstable/ai/AiError.d.ts.map +1 -1
- package/dist/unstable/ai/AiError.js +1 -3
- package/dist/unstable/ai/AiError.js.map +1 -1
- package/dist/unstable/ai/EmbeddingModel.d.ts +130 -0
- package/dist/unstable/ai/EmbeddingModel.d.ts.map +1 -0
- package/dist/unstable/ai/EmbeddingModel.js +127 -0
- package/dist/unstable/ai/EmbeddingModel.js.map +1 -0
- package/dist/unstable/ai/LanguageModel.d.ts.map +1 -1
- package/dist/unstable/ai/LanguageModel.js +18 -8
- package/dist/unstable/ai/LanguageModel.js.map +1 -1
- package/dist/unstable/ai/ResponseIdTracker.js +3 -3
- package/dist/unstable/ai/ResponseIdTracker.js.map +1 -1
- package/dist/unstable/ai/Tool.d.ts +1 -1
- package/dist/unstable/ai/Tool.d.ts.map +1 -1
- package/dist/unstable/ai/Tool.js +1 -1
- package/dist/unstable/ai/Tool.js.map +1 -1
- package/dist/unstable/ai/index.d.ts +17 -0
- package/dist/unstable/ai/index.d.ts.map +1 -1
- package/dist/unstable/ai/index.js +17 -0
- package/dist/unstable/ai/index.js.map +1 -1
- package/dist/unstable/http/Url.d.ts +604 -0
- package/dist/unstable/http/Url.d.ts.map +1 -0
- package/dist/unstable/http/Url.js +256 -0
- package/dist/unstable/http/Url.js.map +1 -0
- package/dist/unstable/http/index.d.ts +4 -0
- package/dist/unstable/http/index.d.ts.map +1 -1
- package/dist/unstable/http/index.js +4 -0
- package/dist/unstable/http/index.js.map +1 -1
- package/dist/unstable/httpapi/HttpApiMiddleware.d.ts +30 -1
- package/dist/unstable/httpapi/HttpApiMiddleware.d.ts.map +1 -1
- package/dist/unstable/httpapi/HttpApiMiddleware.js +27 -0
- package/dist/unstable/httpapi/HttpApiMiddleware.js.map +1 -1
- package/package.json +1 -1
- package/src/Effect.ts +7 -6
- package/src/FileSystem.ts +2 -1
- package/src/Graph.ts +2 -1
- package/src/MutableHashMap.ts +9 -0
- package/src/MutableHashSet.ts +9 -0
- package/src/Resource.ts +2 -1
- package/src/SubscriptionRef.ts +2 -1
- package/src/TxDeferred.ts +2 -2
- package/src/TxHashMap.ts +2 -1
- package/src/TxHashSet.ts +2 -2
- package/src/TxPriorityQueue.ts +2 -3
- package/src/TxSemaphore.ts +2 -1
- package/src/internal/effect.ts +11 -4
- package/src/unstable/ai/AiError.ts +1 -3
- package/src/unstable/ai/EmbeddingModel.ts +209 -0
- package/src/unstable/ai/LanguageModel.ts +36 -4
- package/src/unstable/ai/ResponseIdTracker.ts +3 -3
- package/src/unstable/ai/Tool.ts +2 -2
- package/src/unstable/ai/index.ts +18 -0
- package/src/unstable/http/Url.ts +650 -0
- package/src/unstable/http/index.ts +5 -0
- 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
|
|
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> =>
|
|
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.
|
package/src/TxPriorityQueue.ts
CHANGED
|
@@ -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
|
|
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)
|
package/src/TxSemaphore.ts
CHANGED
|
@@ -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 =>
|
|
742
|
+
export const isTxSemaphore = (u: unknown): u is TxSemaphore => hasProperty(u, TypeId)
|
package/src/internal/effect.ts
CHANGED
|
@@ -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
|
-
|
|
3800
|
-
flatMap(
|
|
3801
|
-
|
|
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
|
-
|
|
41
|
+
const sentParts = new Map<object, string>()
|
|
42
42
|
|
|
43
43
|
const none = () => {
|
|
44
|
-
sentParts
|
|
44
|
+
sentParts.clear()
|
|
45
45
|
return Option.none<PrepareResult>()
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
return {
|
|
49
49
|
clearUnsafe() {
|
|
50
|
-
sentParts
|
|
50
|
+
sentParts.clear()
|
|
51
51
|
},
|
|
52
52
|
markParts(parts, responseId) {
|
|
53
53
|
for (let i = 0; i < parts.length; i++) {
|
package/src/unstable/ai/Tool.ts
CHANGED
|
@@ -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
|
|
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 ??
|
|
1213
|
+
parametersSchema: options?.parameters ?? EmptyParams,
|
|
1214
1214
|
successSchema,
|
|
1215
1215
|
failureSchema,
|
|
1216
1216
|
failureMode: options?.failureMode ?? "error",
|
package/src/unstable/ai/index.ts
CHANGED
|
@@ -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.
|