@effect/ai 0.17.0 → 0.18.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.
@@ -1,162 +0,0 @@
1
- import * as Effect from "effect/Effect"
2
- import { CommitPrototype } from "effect/Effectable"
3
- import * as Either from "effect/Either"
4
- import { dual, identity } from "effect/Function"
5
- import * as Option from "effect/Option"
6
- import { pipeArguments } from "effect/Pipeable"
7
- import * as Predicate from "effect/Predicate"
8
- import * as Schedule from "effect/Schedule"
9
- import * as Scope from "effect/Scope"
10
- import type * as AiModel from "../AiModel.js"
11
- import type * as AiPlan from "../AiPlan.js"
12
-
13
- /** @internal */
14
- export const TypeId: AiPlan.TypeId = Symbol.for("@effect/ai/AiPlan") as AiPlan.TypeId
15
-
16
- /** @internal */
17
- export const PlanPrototype = {
18
- ...CommitPrototype,
19
- [TypeId]: TypeId,
20
- commit(this: AiPlan.AiPlan<any, any, any>) {
21
- return buildPlan(this)
22
- },
23
- pipe() {
24
- return pipeArguments(this, arguments)
25
- }
26
- } as any
27
-
28
- const makePlan = <
29
- Steps extends ReadonlyArray<AiPlan.Step<any, any, any>>
30
- >(steps: Steps): AiPlan.AiPlan<any, any, any> => {
31
- const self = Object.create(PlanPrototype)
32
- self.steps = steps
33
- return self
34
- }
35
-
36
- const buildPlan = <Error, Provides, Requires>(
37
- plan: AiPlan.AiPlan<Error, Provides, Requires>
38
- ): Effect.Effect<
39
- AiPlan.Provider<Provides>,
40
- never,
41
- Requires
42
- > =>
43
- Effect.map(Effect.context<Requires>(), (context) => {
44
- return {
45
- use: Effect.fnUntraced(function*<A, E, R>(effect: Effect.Effect<A, E, R>) {
46
- let result: Either.Either<A, E> | undefined = undefined
47
- for (const step of plan.steps) {
48
- if (result !== undefined && Either.isLeft(result) && Option.isSome(step.check)) {
49
- const check = step.check.value(result.left as any)
50
- const isFatalError = !(Effect.isEffect(check) ? yield* check : check)
51
- if (isFatalError) break
52
- }
53
- const retryOptions = getRetryOptions(step)
54
- result = yield* Effect.scopedWith((scope) =>
55
- step.model.buildContext.pipe(
56
- Scope.extend(scope),
57
- Effect.flatMap((context) =>
58
- effect.pipe(
59
- Option.isSome(retryOptions)
60
- ? Effect.retry(retryOptions.value)
61
- : identity,
62
- Effect.provide(context)
63
- )
64
- ),
65
- Effect.provide(context),
66
- Effect.either
67
- )
68
- )
69
- if (Either.isRight(result)) break
70
- }
71
- return yield* result!
72
- })
73
- }
74
- })
75
-
76
- const getRetryOptions = <Error, Provides, Requires>(
77
- step: AiPlan.Step<Error, Provides, Requires>
78
- ): Option.Option<Effect.Retry.Options<any>> => {
79
- if (Option.isNone(step.schedule) && Option.isNone(step.check)) {
80
- return Option.none()
81
- }
82
- return Option.some({
83
- schedule: Option.getOrUndefined(step.schedule),
84
- while: Option.getOrUndefined(step.check)
85
- })
86
- }
87
-
88
- /** @internal */
89
- export const make = <Provides, Requires, EW, Out, ES, RW = never, RS = never>(
90
- options: {
91
- readonly model: AiModel.AiModel<Provides, Requires>
92
- readonly attempts?: number | undefined
93
- readonly while?: ((error: EW) => boolean | Effect.Effect<boolean, never, RW>) | undefined
94
- readonly schedule?: Schedule.Schedule<Out, ES, RS> | undefined
95
- }
96
- ): AiPlan.AiPlan<EW & ES, Provides, RW | RS | Requires> =>
97
- makePlan([{
98
- model: options.model,
99
- check: Option.fromNullable(options?.while) as any,
100
- schedule: resolveSchedule(options ?? {})
101
- }])
102
-
103
- /** @internal */
104
- export const withFallback = dual(2, <
105
- E,
106
- Provides,
107
- Requires,
108
- Provides2 extends Provides,
109
- Requires2,
110
- Out,
111
- EW,
112
- ES,
113
- RW = never,
114
- RS = never
115
- >(
116
- self: AiPlan.AiPlan<E, Provides, Requires>,
117
- options: {
118
- readonly model: AiModel.AiModel<Provides2, Requires2>
119
- readonly attempts?: number | undefined
120
- readonly while?: ((error: EW) => boolean | Effect.Effect<boolean, never, RW>) | undefined
121
- readonly schedule?: Schedule.Schedule<Out, ES, RS> | undefined
122
- }
123
- ): AiPlan.AiPlan<E & EW & ES, Provides & Provides2, Requires | Requires2 | RW | RS> =>
124
- makePlan([
125
- ...self.steps,
126
- {
127
- model: options.model,
128
- check: Option.fromNullable(options.while) as any,
129
- schedule: resolveSchedule(options)
130
- }
131
- ]))
132
-
133
- const resolveSchedule = <E, R, Out, R2>(options: {
134
- readonly attempts?: number | undefined
135
- readonly schedule?: Schedule.Schedule<Out, E, R2> | undefined
136
- }): Option.Option<Schedule.Schedule<Out, E, R | R2>> => {
137
- if (
138
- Predicate.isUndefined(options.attempts) &&
139
- Predicate.isUndefined(options.schedule)
140
- ) return Option.none()
141
- let schedule = (options.schedule ?? Schedule.forever) as Schedule.Schedule<any, E, R | R2>
142
- if (Predicate.isNotUndefined(options.attempts)) {
143
- // In an `AiPlan`, the `attempts` represents the total number of times to
144
- // attempt the call, not the number of retries, thus we subtract one from
145
- // the total number of recurrences
146
- schedule = Schedule.intersect(schedule, Schedule.recurs(options.attempts - 1))
147
- }
148
- return Option.some(schedule)
149
- }
150
-
151
- /** @internal */
152
- export const concatSteps = dual<
153
- <Error2, Provides2, Requires2>(
154
- other: AiPlan.AiPlan<Error2, Provides2, Requires2>
155
- ) => <Error, Provides, Requires>(
156
- self: AiPlan.AiPlan<Error, Provides, Requires>
157
- ) => AiPlan.AiPlan<Error & Error2, Provides & Provides2, Requires | Requires2>,
158
- <Error, Provides, Requires, Error2, Provides2, Requires2>(
159
- self: AiPlan.AiPlan<Error, Provides, Requires>,
160
- other: AiPlan.AiPlan<Error2, Provides2, Requires2>
161
- ) => AiPlan.AiPlan<Error & Error2, Provides & Provides2, Requires | Requires2>
162
- >(2, (self, other) => makePlan([...self.steps, ...other.steps]))