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