liminal 0.15.0 → 0.17.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.
- package/CHANGELOG.md +12 -0
- package/Digest.ts +30 -0
- package/Envelope.ts +16 -0
- package/F/F.ts +1 -0
- package/{L.ts → L/L.ts} +9 -4
- package/L/append.ts +14 -0
- package/{assistant.ts → L/assistant.ts} +10 -9
- package/{assistantSchema.ts → L/assistantSchema.ts} +8 -7
- package/{assistantStream.ts → L/assistantStream.ts} +8 -11
- package/L/branch.ts +20 -0
- package/L/clear.ts +14 -0
- package/L/disable.ts +13 -0
- package/L/enable.ts +24 -0
- package/L/events.ts +11 -0
- package/L/json.ts +12 -0
- package/L/line.ts +22 -0
- package/{handle.ts → L/listen.ts} +6 -5
- package/L/messages.ts +10 -0
- package/L/prev.ts +4 -0
- package/L/provide.ts +10 -0
- package/L/self.ts +5 -0
- package/L/send.ts +56 -0
- package/L/system.ts +25 -0
- package/L/thread.ts +16 -0
- package/L/toolkit.ts +14 -0
- package/{user.test.ts → L/user.test.ts} +5 -2
- package/L/user.ts +32 -0
- package/LEvent.ts +23 -13
- package/Thread.ts +67 -0
- package/dist/Digest.d.ts +17 -0
- package/dist/Digest.js +7 -0
- package/dist/Digest.js.map +1 -0
- package/dist/Envelope.d.ts +13 -0
- package/dist/Envelope.js +2 -0
- package/dist/Envelope.js.map +1 -0
- package/dist/F/F.d.ts +1 -0
- package/dist/F/F.js +2 -0
- package/dist/F/F.js.map +1 -0
- package/dist/{L.d.ts → L/L.d.ts} +9 -4
- package/dist/{L.js → L/L.js} +9 -4
- package/dist/L/L.js.map +1 -0
- package/dist/{append.d.ts → L/append.d.ts} +3 -3
- package/dist/L/append.js +10 -0
- package/dist/L/append.js.map +1 -0
- package/dist/{assistant.d.ts → L/assistant.d.ts} +3 -3
- package/dist/{assistant.js → L/assistant.js} +8 -8
- package/dist/L/assistant.js.map +1 -0
- package/dist/{assistantSchema.d.ts → L/assistantSchema.d.ts} +4 -4
- package/dist/{assistantSchema.js → L/assistantSchema.js} +5 -5
- package/dist/L/assistantSchema.js.map +1 -0
- package/dist/{assistantStream.d.ts → L/assistantStream.d.ts} +3 -3
- package/dist/{assistantStream.js → L/assistantStream.js} +6 -6
- package/dist/L/assistantStream.js.map +1 -0
- package/dist/L/branch.d.ts +3 -0
- package/dist/L/branch.js +19 -0
- package/dist/L/branch.js.map +1 -0
- package/dist/{clear.d.ts → L/clear.d.ts} +3 -3
- package/dist/L/clear.js +12 -0
- package/dist/L/clear.js.map +1 -0
- package/dist/{disable.d.ts → L/disable.d.ts} +2 -2
- package/dist/L/disable.js +10 -0
- package/dist/L/disable.js.map +1 -0
- package/dist/{enable.d.ts → L/enable.d.ts} +2 -2
- package/dist/L/enable.js +13 -0
- package/dist/L/enable.js.map +1 -0
- package/dist/L/events.d.ts +5 -0
- package/dist/L/events.js +6 -0
- package/dist/L/events.js.map +1 -0
- package/dist/L/json.d.ts +5 -0
- package/dist/L/json.js +8 -0
- package/dist/L/json.js.map +1 -0
- package/dist/L/line.d.ts +5 -0
- package/dist/L/line.js +11 -0
- package/dist/L/line.js.map +1 -0
- package/dist/{handle.d.ts → L/listen.d.ts} +4 -4
- package/dist/{handle.js → L/listen.js} +4 -4
- package/dist/L/listen.js.map +1 -0
- package/dist/{messages.d.ts → L/messages.d.ts} +2 -2
- package/dist/L/messages.js +5 -0
- package/dist/L/messages.js.map +1 -0
- package/dist/L/prev.d.ts +5 -0
- package/dist/L/prev.js +5 -0
- package/dist/L/prev.js.map +1 -0
- package/dist/L/provide.d.ts +3 -0
- package/dist/L/provide.js +4 -0
- package/dist/L/provide.js.map +1 -0
- package/dist/L/self.d.ts +3 -0
- package/dist/L/self.js +4 -0
- package/dist/L/self.js.map +1 -0
- package/dist/L/send.d.ts +6 -0
- package/dist/L/send.js +34 -0
- package/dist/L/send.js.map +1 -0
- package/dist/L/system.d.ts +5 -0
- package/dist/L/system.js +14 -0
- package/dist/L/system.js.map +1 -0
- package/dist/L/thread.d.ts +3 -0
- package/dist/L/thread.js +15 -0
- package/dist/L/thread.js.map +1 -0
- package/dist/L/toolkit.d.ts +4 -0
- package/dist/L/toolkit.js +9 -0
- package/dist/L/toolkit.js.map +1 -0
- package/dist/L/user.d.ts +6 -0
- package/dist/{user.js → L/user.js} +3 -3
- package/dist/L/user.js.map +1 -0
- package/dist/L/user.test.js.map +1 -0
- package/dist/LEvent.d.ts +143 -15
- package/dist/LEvent.js +12 -9
- package/dist/LEvent.js.map +1 -1
- package/dist/Thread.d.ts +52 -0
- package/dist/Thread.js +32 -0
- package/dist/Thread.js.map +1 -0
- package/dist/index.d.ts +6 -3
- package/dist/index.js +6 -3
- package/dist/index.js.map +1 -1
- package/dist/patterns/Debate.d.ts +1 -0
- package/dist/patterns/Debate.js +3 -0
- package/dist/patterns/Debate.js.map +1 -0
- package/dist/patterns/Model.d.ts +6 -0
- package/dist/patterns/{coalesce_models.js → Model.js} +5 -6
- package/dist/patterns/Model.js.map +1 -0
- package/dist/patterns/Route.d.ts +3 -0
- package/dist/patterns/Route.js +14 -0
- package/dist/patterns/Route.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/util/JsonValue.js.map +1 -1
- package/dist/util/NeverTool.d.ts +3 -0
- package/dist/util/NeverTool.js +3 -0
- package/dist/util/NeverTool.js.map +1 -0
- package/dist/util/Taggable.d.ts +5 -5
- package/dist/util/Taggable.js +10 -15
- package/dist/util/Taggable.js.map +1 -1
- package/dist/util/extract.d.ts +3 -0
- package/dist/util/extract.js +2 -0
- package/dist/util/extract.js.map +1 -0
- package/dist/util/messageCodec.d.ts +98 -0
- package/dist/util/messageCodec.js +5 -0
- package/dist/util/messageCodec.js.map +1 -0
- package/dist/util/{fixRaw.js → normalizeRaw.js} +1 -1
- package/dist/util/normalizeRaw.js.map +1 -0
- package/dist/util/prefix.d.ts +1 -0
- package/dist/util/prefix.js +2 -0
- package/dist/util/prefix.js.map +1 -0
- package/dist/util/raw.d.ts +6 -0
- package/dist/util/raw.js +5 -0
- package/dist/util/raw.js.map +1 -0
- package/index.ts +6 -3
- package/package.json +22 -9
- package/patterns/Debate.ts +2 -0
- package/patterns/{coalesce_models.ts → Model.ts} +6 -7
- package/patterns/{match_gist.ts → Route.ts} +11 -9
- package/util/JsonValue.ts +2 -2
- package/util/NeverTool.ts +10 -0
- package/util/Taggable.ts +27 -34
- package/util/extract.ts +7 -0
- package/util/messageCodec.ts +5 -0
- package/util/prefix.ts +1 -0
- package/util/raw.ts +27 -0
- package/LPretty.ts +0 -41
- package/Strand.ts +0 -49
- package/append.ts +0 -13
- package/branch.ts +0 -26
- package/clear.ts +0 -15
- package/disable.ts +0 -8
- package/dist/L.js.map +0 -1
- package/dist/LPretty.d.ts +0 -4
- package/dist/LPretty.js +0 -37
- package/dist/LPretty.js.map +0 -1
- package/dist/Strand.d.ts +0 -36
- package/dist/Strand.js +0 -18
- package/dist/Strand.js.map +0 -1
- package/dist/append.js +0 -10
- package/dist/append.js.map +0 -1
- package/dist/assistant.js.map +0 -1
- package/dist/assistantSchema.js.map +0 -1
- package/dist/assistantStream.js.map +0 -1
- package/dist/branch.d.ts +0 -4
- package/dist/branch.js +0 -18
- package/dist/branch.js.map +0 -1
- package/dist/clear.js +0 -14
- package/dist/clear.js.map +0 -1
- package/dist/disable.js +0 -7
- package/dist/disable.js.map +0 -1
- package/dist/enable.js +0 -6
- package/dist/enable.js.map +0 -1
- package/dist/events.d.ts +0 -5
- package/dist/events.js +0 -6
- package/dist/events.js.map +0 -1
- package/dist/handle.js.map +0 -1
- package/dist/messages.js +0 -5
- package/dist/messages.js.map +0 -1
- package/dist/patterns/coalesce_models.d.ts +0 -6
- package/dist/patterns/coalesce_models.js.map +0 -1
- package/dist/patterns/match_gist.d.ts +0 -3
- package/dist/patterns/match_gist.js +0 -16
- package/dist/patterns/match_gist.js.map +0 -1
- package/dist/sequence.d.ts +0 -2
- package/dist/sequence.js +0 -5
- package/dist/sequence.js.map +0 -1
- package/dist/strand_.d.ts +0 -4
- package/dist/strand_.js +0 -8
- package/dist/strand_.js.map +0 -1
- package/dist/system.d.ts +0 -5
- package/dist/system.js +0 -12
- package/dist/system.js.map +0 -1
- package/dist/user.d.ts +0 -4
- package/dist/user.js.map +0 -1
- package/dist/user.test.js.map +0 -1
- package/dist/userJson.d.ts +0 -6
- package/dist/userJson.js +0 -9
- package/dist/userJson.js.map +0 -1
- package/dist/util/Sequence.d.ts +0 -2
- package/dist/util/Sequence.js +0 -2
- package/dist/util/Sequence.js.map +0 -1
- package/dist/util/fixRaw.js.map +0 -1
- package/enable.ts +0 -15
- package/events.ts +0 -10
- package/messages.ts +0 -9
- package/sequence.ts +0 -9
- package/strand_.ts +0 -11
- package/system.ts +0 -12
- package/user.ts +0 -21
- package/userJson.ts +0 -14
- package/util/Sequence.ts +0 -11
- /package/dist/{user.test.d.ts → L/user.test.d.ts} +0 -0
- /package/dist/util/{fixRaw.d.ts → normalizeRaw.d.ts} +0 -0
- /package/util/{fixRaw.ts → normalizeRaw.ts} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# liminal
|
|
2
2
|
|
|
3
|
+
## 0.17.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 8212083: Refactor L.sequence -> L.line. Decouple thread effects from the providing of effects via L.provide.
|
|
8
|
+
|
|
9
|
+
## 0.16.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- 2e96076: Refactoring "strands" into "threads", which can provide a handle with which to operate on the thread context outside of the thread's sequencers arguments.
|
|
14
|
+
|
|
3
15
|
## 0.15.0
|
|
4
16
|
|
|
5
17
|
### Minor Changes
|
package/Digest.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import * as Effect from "effect/Effect"
|
|
2
|
+
import * as Layer from "effect/Layer"
|
|
3
|
+
import * as Option from "effect/Option"
|
|
4
|
+
import * as Schema from "effect/Schema"
|
|
5
|
+
import type { Thread } from "./Thread.ts"
|
|
6
|
+
import { prefix } from "./util/prefix.ts"
|
|
7
|
+
|
|
8
|
+
export const DigestTypeId: unique symbol = Symbol.for(prefix("Digest"))
|
|
9
|
+
export type DigestTypeId = typeof DigestTypeId
|
|
10
|
+
|
|
11
|
+
export declare const Digest: <const K extends string, A = string, I = string>(
|
|
12
|
+
key: K,
|
|
13
|
+
schema?: Schema.Schema<A, I>,
|
|
14
|
+
) => <Self>() => DigestClass<K, A, I, Self>
|
|
15
|
+
|
|
16
|
+
export interface DigestClass<K extends string, A, I, Self> extends Effect.Effect<A, never, Self> {
|
|
17
|
+
new(_: never): this
|
|
18
|
+
|
|
19
|
+
readonly Type: A
|
|
20
|
+
readonly Encoded: I
|
|
21
|
+
readonly [DigestTypeId]: DigestTypeId
|
|
22
|
+
readonly key: K
|
|
23
|
+
readonly digest: Effect.Effect<void, never, Self>
|
|
24
|
+
readonly layer: <E, R>(
|
|
25
|
+
f: (
|
|
26
|
+
state: Option.Option<A>,
|
|
27
|
+
inbox: Thread,
|
|
28
|
+
) => Effect.Effect<A, E, R>,
|
|
29
|
+
) => Layer.Layer<Self, E, Exclude<R, Self | Thread>>
|
|
30
|
+
}
|
package/Envelope.ts
ADDED
package/F/F.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "../L/json.ts"
|
package/{L.ts → L/L.ts}
RENAMED
|
@@ -4,12 +4,17 @@ export * from "./assistantSchema.ts"
|
|
|
4
4
|
export * from "./assistantStream.ts"
|
|
5
5
|
export * from "./branch.ts"
|
|
6
6
|
export * from "./clear.ts"
|
|
7
|
+
export * from "./disable.ts"
|
|
7
8
|
export * from "./enable.ts"
|
|
8
9
|
export * from "./events.ts"
|
|
9
|
-
export * from "./
|
|
10
|
+
export * from "./line.ts"
|
|
11
|
+
export * from "./listen.ts"
|
|
10
12
|
export * from "./messages.ts"
|
|
11
|
-
export * from "./
|
|
12
|
-
export * from "./
|
|
13
|
+
export * from "./prev.ts"
|
|
14
|
+
export * from "./provide.ts"
|
|
15
|
+
export * from "./self.ts"
|
|
16
|
+
export * from "./send.ts"
|
|
13
17
|
export * from "./system.ts"
|
|
18
|
+
export * from "./thread.ts"
|
|
19
|
+
export * from "./toolkit.ts"
|
|
14
20
|
export * from "./user.ts"
|
|
15
|
-
export * from "./userJson.ts"
|
package/L/append.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Message } from "@effect/ai/AiInput"
|
|
2
|
+
import * as Effect from "effect/Effect"
|
|
3
|
+
import { MessagesAppendedEvent } from "../LEvent.ts"
|
|
4
|
+
import type { Thread } from "../Thread.ts"
|
|
5
|
+
import { self } from "./self.ts"
|
|
6
|
+
|
|
7
|
+
/** Append messages to the thread. */
|
|
8
|
+
export const append: (
|
|
9
|
+
...messages: Array<Message>
|
|
10
|
+
) => Effect.Effect<void, never, Thread> = Effect.fnUntraced(function*(...messages) {
|
|
11
|
+
const { state, events } = yield* self
|
|
12
|
+
state.messages.push(...messages)
|
|
13
|
+
yield* events.publish(MessagesAppendedEvent.make({ messages }))
|
|
14
|
+
})
|
|
@@ -1,28 +1,29 @@
|
|
|
1
1
|
import type { AiError } from "@effect/ai/AiError"
|
|
2
2
|
import { AssistantMessage, TextPart } from "@effect/ai/AiInput"
|
|
3
3
|
import { AiLanguageModel } from "@effect/ai/AiLanguageModel"
|
|
4
|
-
import * as AiToolkit from "@effect/ai/AiToolkit"
|
|
5
4
|
import * as Effect from "effect/Effect"
|
|
6
5
|
import * as Option from "effect/Option"
|
|
6
|
+
import type { Thread } from "../Thread.ts"
|
|
7
7
|
import { append } from "./append.ts"
|
|
8
|
-
import {
|
|
8
|
+
import { self } from "./self.ts"
|
|
9
|
+
import { toolkit } from "./toolkit.ts"
|
|
9
10
|
|
|
10
|
-
/** Infer an assistant message and append it to the
|
|
11
|
-
export const assistant: Effect.Effect<string, AiError, AiLanguageModel |
|
|
11
|
+
/** Infer an assistant message and append it to the thread. */
|
|
12
|
+
export const assistant: Effect.Effect<string, AiError, AiLanguageModel | Thread> = Effect.gen(function*() {
|
|
12
13
|
const model = yield* AiLanguageModel
|
|
13
|
-
const { system, messages
|
|
14
|
+
const { state: { system, messages: prompt } } = yield* self
|
|
14
15
|
let { text, results } = yield* model.generateText({
|
|
15
16
|
system: Option.getOrUndefined(system),
|
|
16
|
-
prompt
|
|
17
|
-
toolkit
|
|
17
|
+
prompt,
|
|
18
|
+
toolkit,
|
|
18
19
|
})
|
|
19
20
|
// TODO: this shouldn't be necessary. Bug in Effect AI?
|
|
20
21
|
if (!text.trim()) {
|
|
21
22
|
text = results.values().next().value?.result as never as string
|
|
22
23
|
}
|
|
23
24
|
yield* append(
|
|
24
|
-
|
|
25
|
-
parts: [
|
|
25
|
+
AssistantMessage.make({
|
|
26
|
+
parts: [TextPart.make({ text })],
|
|
26
27
|
}),
|
|
27
28
|
)
|
|
28
29
|
return text
|
|
@@ -5,21 +5,22 @@ import * as Effect from "effect/Effect"
|
|
|
5
5
|
import * as Option from "effect/Option"
|
|
6
6
|
import * as Schema from "effect/Schema"
|
|
7
7
|
import * as SchemaAST from "effect/SchemaAST"
|
|
8
|
+
import type { Thread } from "../Thread.ts"
|
|
9
|
+
import { encodeJsonc, type JsonValue } from "../util/JsonValue.ts"
|
|
8
10
|
import { append } from "./append.ts"
|
|
9
|
-
import {
|
|
10
|
-
import { encodeJsonc, type JsonValue } from "./util/JsonValue.ts"
|
|
11
|
+
import { self } from "./self.ts"
|
|
11
12
|
|
|
12
13
|
/** Infer a structured assistant message and append its JSON representation to the conversation. */
|
|
13
14
|
export const assistantSchema: {
|
|
14
15
|
<F extends Record<string, Schema.Schema.AnyNoContext>>(
|
|
15
16
|
fields: F,
|
|
16
|
-
): Effect.Effect<{ [K in keyof F]: Schema.Schema.Type<F[K]> }, AiError, AiLanguageModel |
|
|
17
|
+
): Effect.Effect<{ [K in keyof F]: Schema.Schema.Type<F[K]> }, AiError, AiLanguageModel | Thread>
|
|
17
18
|
<O, I extends JsonValue>(
|
|
18
19
|
schema: Schema.Schema<O, I, never>,
|
|
19
|
-
): Effect.Effect<O, AiError, AiLanguageModel |
|
|
20
|
+
): Effect.Effect<O, AiError, AiLanguageModel | Thread>
|
|
20
21
|
} = Effect.fnUntraced(function*(schema) {
|
|
21
22
|
const model = yield* AiLanguageModel
|
|
22
|
-
const { system, messages } = yield*
|
|
23
|
+
const { state: { system, messages } } = yield* self
|
|
23
24
|
|
|
24
25
|
const isSchema = Schema.isSchema(schema)
|
|
25
26
|
const schema_ = isSchema ? schema : Schema.Struct(schema) as Schema.Schema.AnyNoContext
|
|
@@ -35,9 +36,9 @@ export const assistantSchema: {
|
|
|
35
36
|
)
|
|
36
37
|
|
|
37
38
|
yield* append(
|
|
38
|
-
|
|
39
|
+
AssistantMessage.make({
|
|
39
40
|
parts: [
|
|
40
|
-
|
|
41
|
+
TextPart.make({
|
|
41
42
|
text: yield* encodeJsonc(schema_)(value),
|
|
42
43
|
}),
|
|
43
44
|
],
|
|
@@ -1,25 +1,22 @@
|
|
|
1
1
|
import type { AiError } from "@effect/ai/AiError"
|
|
2
2
|
import { AiLanguageModel } from "@effect/ai/AiLanguageModel"
|
|
3
3
|
import type { AiResponse } from "@effect/ai/AiResponse"
|
|
4
|
-
import * as AiToolkit from "@effect/ai/AiToolkit"
|
|
5
4
|
import * as Effect from "effect/Effect"
|
|
6
5
|
import * as Option from "effect/Option"
|
|
7
6
|
import * as Stream from "effect/Stream"
|
|
8
|
-
import {
|
|
7
|
+
import type { Thread } from "../Thread.ts"
|
|
8
|
+
import { self } from "./self.ts"
|
|
9
|
+
import { toolkit } from "./toolkit.ts"
|
|
9
10
|
|
|
10
|
-
/** Get a
|
|
11
|
-
export const assistantStream: Stream.Stream<
|
|
12
|
-
AiResponse,
|
|
13
|
-
AiError,
|
|
14
|
-
AiLanguageModel | Strand
|
|
15
|
-
> = Stream.unwrap(
|
|
11
|
+
/** Get a stream of an assistant message (does not append the message to the thread). */
|
|
12
|
+
export const assistantStream: Stream.Stream<AiResponse, AiError, AiLanguageModel | Thread> = Stream.unwrap(
|
|
16
13
|
Effect.gen(function*() {
|
|
17
14
|
const model = yield* AiLanguageModel
|
|
18
|
-
const { system, messages
|
|
15
|
+
const { state: { system, messages: prompt } } = yield* self
|
|
19
16
|
return model.streamText({
|
|
20
17
|
system: Option.getOrUndefined(system),
|
|
21
|
-
prompt
|
|
22
|
-
toolkit
|
|
18
|
+
prompt,
|
|
19
|
+
toolkit,
|
|
23
20
|
})
|
|
24
21
|
}),
|
|
25
22
|
)
|
package/L/branch.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import * as Effect from "effect/Effect"
|
|
2
|
+
import * as Option from "effect/Option"
|
|
3
|
+
import * as PubSub from "effect/PubSub"
|
|
4
|
+
import type { LEvent } from "../LEvent.ts"
|
|
5
|
+
import { Thread, ThreadState } from "../Thread.ts"
|
|
6
|
+
import { self } from "./self.ts"
|
|
7
|
+
|
|
8
|
+
export const branch: Effect.Effect<Thread, never, Thread> = Effect.gen(function*() {
|
|
9
|
+
const parent = yield* self
|
|
10
|
+
return Thread({
|
|
11
|
+
id: parent.id,
|
|
12
|
+
parent: Option.some(parent),
|
|
13
|
+
events: yield* PubSub.unbounded<LEvent>(),
|
|
14
|
+
state: ThreadState.make({
|
|
15
|
+
system: parent.state.system,
|
|
16
|
+
messages: [...parent.state.messages ?? []],
|
|
17
|
+
}),
|
|
18
|
+
tools: parent.tools.pipe(Option.map((v) => new Set(v))),
|
|
19
|
+
})
|
|
20
|
+
})
|
package/L/clear.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Message } from "@effect/ai/AiInput"
|
|
2
|
+
import * as Effect from "effect/Effect"
|
|
3
|
+
import { ThreadClearedEvent } from "../LEvent.ts"
|
|
4
|
+
import type { Thread } from "../Thread.ts"
|
|
5
|
+
import { self } from "./self.ts"
|
|
6
|
+
|
|
7
|
+
/** Clear the thread of messages. */
|
|
8
|
+
export const clear: Effect.Effect<Array<Message>, never, Thread> = Effect.gen(function*() {
|
|
9
|
+
const { state, events } = yield* self
|
|
10
|
+
const cleared = state.messages
|
|
11
|
+
state.messages = []
|
|
12
|
+
yield* events.publish(ThreadClearedEvent.make({ cleared }))
|
|
13
|
+
return cleared
|
|
14
|
+
})
|
package/L/disable.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as AiTool from "@effect/ai/AiTool"
|
|
2
|
+
import * as Effect from "effect/Effect"
|
|
3
|
+
import * as Option from "effect/Option"
|
|
4
|
+
import type { Thread } from "../Thread.ts"
|
|
5
|
+
import type { NeverTool } from "../util/NeverTool.ts"
|
|
6
|
+
import { self } from "./self.ts"
|
|
7
|
+
|
|
8
|
+
export const disable = (tool: AiTool.Any): Effect.Effect<void, never, Thread> =>
|
|
9
|
+
Effect.map(self, ({ tools }) => {
|
|
10
|
+
if (Option.isSome(tools)) {
|
|
11
|
+
tools.value.delete(tool as NeverTool)
|
|
12
|
+
}
|
|
13
|
+
})
|
package/L/enable.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { AiTool, AnyStructSchema, Handler } from "@effect/ai/AiTool"
|
|
2
|
+
import * as Effect from "effect/Effect"
|
|
3
|
+
import * as Option from "effect/Option"
|
|
4
|
+
import type { Schema } from "effect/Schema"
|
|
5
|
+
import type { Thread } from "../Thread.ts"
|
|
6
|
+
import type { NeverTool } from "../util/NeverTool.ts"
|
|
7
|
+
import { self } from "./self.ts"
|
|
8
|
+
|
|
9
|
+
export const enable = <
|
|
10
|
+
K extends string,
|
|
11
|
+
E extends Schema.All,
|
|
12
|
+
R,
|
|
13
|
+
>(
|
|
14
|
+
tool: AiTool<K, AnyStructSchema, Schema.Any, E, R>,
|
|
15
|
+
): Effect.Effect<void, E, Handler<K> | Thread | R> =>
|
|
16
|
+
Effect.map(self, (thread) => {
|
|
17
|
+
const tool_: NeverTool = tool as never
|
|
18
|
+
Option.match(thread.tools, {
|
|
19
|
+
onSome: (value) => value.add(tool_),
|
|
20
|
+
onNone: () => {
|
|
21
|
+
thread.tools = Option.some(new Set([tool_]))
|
|
22
|
+
},
|
|
23
|
+
})
|
|
24
|
+
})
|
package/L/events.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as Effect from "effect/Effect"
|
|
2
|
+
import * as Stream from "effect/Stream"
|
|
3
|
+
import type { LEvent } from "../LEvent.ts"
|
|
4
|
+
import type { Thread } from "../Thread.ts"
|
|
5
|
+
import { self } from "./self.ts"
|
|
6
|
+
|
|
7
|
+
/** A stream of thread events. */
|
|
8
|
+
export const events: Stream.Stream<LEvent, never, Thread> = self.pipe(
|
|
9
|
+
Effect.map(({ events }) => Stream.fromPubSub(events)),
|
|
10
|
+
Stream.unwrap,
|
|
11
|
+
)
|
package/L/json.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import * as Effect from "effect/Effect"
|
|
2
|
+
import type * as Schema from "effect/Schema"
|
|
3
|
+
import { encodeJsonc, type JsonValue } from "../util/JsonValue.ts"
|
|
4
|
+
|
|
5
|
+
/** Stringify and append some JSON as a user message to the conversation. */
|
|
6
|
+
export const json: <A, I extends JsonValue>(
|
|
7
|
+
value: A,
|
|
8
|
+
schema?: Schema.Schema<A, I>,
|
|
9
|
+
) => Effect.Effect<string> = Effect.fnUntraced(function*(value, schema) {
|
|
10
|
+
const encoded = schema ? encodeJsonc(schema)(value) : JSON.stringify(value, null, 2)
|
|
11
|
+
return `\`\`\`json${schema ? "c" : ""}\n${encoded}\n\`\`\``
|
|
12
|
+
})
|
package/L/line.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import * as Effect from "effect/Effect"
|
|
2
|
+
import { prev } from "./prev.ts"
|
|
3
|
+
|
|
4
|
+
export interface line<RIn = never, E = never, ROut = never> {
|
|
5
|
+
<Arg extends Array<Effect.All.EffectAny>>(
|
|
6
|
+
...steps: Arg
|
|
7
|
+
): Effect.Effect<
|
|
8
|
+
Arg extends [] ? void
|
|
9
|
+
: Arg extends [...infer _0, infer L extends Effect.All.EffectAny] ? Effect.Effect.Success<L>
|
|
10
|
+
: never,
|
|
11
|
+
Effect.Effect.Error<Arg[number]> | E,
|
|
12
|
+
Exclude<Effect.Effect.Context<Arg[number]>, RIn> | ROut
|
|
13
|
+
>
|
|
14
|
+
}
|
|
15
|
+
export const line: line = Effect.fnUntraced(function*(...steps) {
|
|
16
|
+
let acc: unknown
|
|
17
|
+
while (steps.length) {
|
|
18
|
+
const current = steps.shift()!
|
|
19
|
+
acc = yield* (current.pipe(Effect.provideService(prev, acc)) as Effect.Effect<any>)
|
|
20
|
+
}
|
|
21
|
+
return acc as never
|
|
22
|
+
})
|
|
@@ -2,15 +2,16 @@ import * as Effect from "effect/Effect"
|
|
|
2
2
|
import type { RuntimeFiber } from "effect/Fiber"
|
|
3
3
|
import * as Scope from "effect/Scope"
|
|
4
4
|
import * as Stream from "effect/Stream"
|
|
5
|
-
import type { LEvent } from "
|
|
6
|
-
import {
|
|
5
|
+
import type { LEvent } from "../LEvent.ts"
|
|
6
|
+
import type { Thread } from "../Thread.ts"
|
|
7
|
+
import { self } from "./self.ts"
|
|
7
8
|
|
|
8
|
-
/** Attach an event handler to process
|
|
9
|
+
/** Attach an event handler to process thread events. */
|
|
9
10
|
export const listen: <A, E, R>(
|
|
10
11
|
f: (event: LEvent) => Effect.Effect<A, E, R>,
|
|
11
|
-
) => Effect.Effect<RuntimeFiber<void, E>, never,
|
|
12
|
+
) => Effect.Effect<RuntimeFiber<void, E>, never, Thread | R | Scope.Scope> = Effect.fnUntraced(function*(f) {
|
|
12
13
|
const latch = yield* Effect.makeLatch(false)
|
|
13
|
-
const { events } = yield*
|
|
14
|
+
const { events } = yield* self
|
|
14
15
|
const dequeue = yield* events.subscribe
|
|
15
16
|
const fiber = yield* latch.open.pipe(
|
|
16
17
|
Effect.zipRight(
|
package/L/messages.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Message } from "@effect/ai/AiInput"
|
|
2
|
+
import * as Effect from "effect/Effect"
|
|
3
|
+
import type { Thread } from "../Thread.ts"
|
|
4
|
+
import { self } from "./self.ts"
|
|
5
|
+
|
|
6
|
+
/** Get a copy of the current list of messages. */
|
|
7
|
+
export const messages: Effect.Effect<Array<Message>, never, Thread> = Effect.map(
|
|
8
|
+
self,
|
|
9
|
+
({ state: { messages: [...messages] } }) => messages,
|
|
10
|
+
)
|
package/L/prev.ts
ADDED
package/L/provide.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import * as Effect from "effect/Effect"
|
|
2
|
+
import type { Thread } from "../Thread.ts"
|
|
3
|
+
import { self } from "./self.ts"
|
|
4
|
+
|
|
5
|
+
export const provide = <E, R>(
|
|
6
|
+
thread: Effect.Effect<Thread, E, R>,
|
|
7
|
+
) =>
|
|
8
|
+
<A1, E1, R1>(
|
|
9
|
+
a: Effect.Effect<A1, E1, R1>,
|
|
10
|
+
): Effect.Effect<A1, E | E1, R | Exclude<R1, Thread>> => Effect.provideServiceEffect(self, thread)(a)
|
package/L/self.ts
ADDED
package/L/send.ts
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import * as AiInput from "@effect/ai/AiInput"
|
|
2
|
+
import * as Array from "effect/Array"
|
|
3
|
+
import * as Effect from "effect/Effect"
|
|
4
|
+
import type { YieldWrap } from "effect/Utils"
|
|
5
|
+
import type { Envelope } from "../Envelope.ts"
|
|
6
|
+
import type { Thread } from "../Thread.ts"
|
|
7
|
+
import type { ExtractE, ExtractR } from "../util/extract.ts"
|
|
8
|
+
import { raw } from "../util/raw.ts"
|
|
9
|
+
import { normalize, type TaggableArg0, type TaggableArgRest } from "../util/Taggable.ts"
|
|
10
|
+
import { append } from "./append.ts"
|
|
11
|
+
import { self } from "./self.ts"
|
|
12
|
+
|
|
13
|
+
export const send = (envelope: Envelope) =>
|
|
14
|
+
Effect.fnUntraced(function*<
|
|
15
|
+
A0 extends TaggableArg0,
|
|
16
|
+
ARest extends TaggableArgRest<A0>,
|
|
17
|
+
>(
|
|
18
|
+
a0: A0,
|
|
19
|
+
...aRest: ARest
|
|
20
|
+
): Generator<
|
|
21
|
+
YieldWrap<
|
|
22
|
+
Effect.Effect<
|
|
23
|
+
void,
|
|
24
|
+
ExtractE<A0 | ARest[number]>,
|
|
25
|
+
ExtractR<A0 | ARest[number]> | Thread
|
|
26
|
+
>
|
|
27
|
+
>,
|
|
28
|
+
void,
|
|
29
|
+
never
|
|
30
|
+
> {
|
|
31
|
+
const text = yield* normalize(a0, ...aRest)
|
|
32
|
+
if (!text) return
|
|
33
|
+
const { to, cc, bcc } = envelope
|
|
34
|
+
const ccHeader = cc?.length
|
|
35
|
+
? yield* raw`; ${Effect.all(cc).pipe(Effect.map(Array.join(", ")))}`
|
|
36
|
+
: ""
|
|
37
|
+
const headers = raw`[FROM: ${self}${ccHeader}]`
|
|
38
|
+
const knownRecipients = [...to ?? [], ...cc ?? []]
|
|
39
|
+
const program = append(
|
|
40
|
+
AiInput.UserMessage.make({
|
|
41
|
+
parts: [
|
|
42
|
+
AiInput.TextPart.make({
|
|
43
|
+
text: `${headers}\n${text}`,
|
|
44
|
+
}),
|
|
45
|
+
],
|
|
46
|
+
}),
|
|
47
|
+
)
|
|
48
|
+
for (const recipient of knownRecipients) {
|
|
49
|
+
yield* program.pipe(Effect.provideService(self, recipient))
|
|
50
|
+
}
|
|
51
|
+
if (bcc?.length) {
|
|
52
|
+
for (const hiddenRecipient of bcc) {
|
|
53
|
+
yield* program.pipe(Effect.provideService(self, hiddenRecipient))
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
})
|
package/L/system.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import * as Effect from "effect/Effect"
|
|
2
|
+
import * as Option from "effect/Option"
|
|
3
|
+
import type { YieldWrap } from "effect/Utils"
|
|
4
|
+
import { SystemSetEvent } from "../LEvent.ts"
|
|
5
|
+
import { normalize, type TaggableArg0, type TaggableArgRest } from "../util/Taggable.ts"
|
|
6
|
+
import { self } from "./self.ts"
|
|
7
|
+
|
|
8
|
+
/** Set the thread's system instruction. */
|
|
9
|
+
export const system = Effect.fnUntraced(function*<
|
|
10
|
+
A0 extends TaggableArg0,
|
|
11
|
+
ARest extends TaggableArgRest<A0>,
|
|
12
|
+
>(
|
|
13
|
+
a0: A0,
|
|
14
|
+
...aRest: ARest
|
|
15
|
+
): Generator<
|
|
16
|
+
YieldWrap<typeof self | ReturnType<typeof normalize<A0, ARest>> | Effect.Effect<boolean>>,
|
|
17
|
+
Option.Option<string>,
|
|
18
|
+
never
|
|
19
|
+
> {
|
|
20
|
+
const { state, events } = yield* self
|
|
21
|
+
const { system } = state
|
|
22
|
+
state.system = a0 ? Option.some(yield* normalize(a0, ...aRest)) : Option.none()
|
|
23
|
+
yield* events.publish(new SystemSetEvent({ system: state.system }))
|
|
24
|
+
return system
|
|
25
|
+
})
|
package/L/thread.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as Effect from "effect/Effect"
|
|
2
|
+
import * as Option from "effect/Option"
|
|
3
|
+
import * as PubSub from "effect/PubSub"
|
|
4
|
+
import type { LEvent } from "../LEvent.ts"
|
|
5
|
+
import { Thread, ThreadId, ThreadState } from "../Thread.ts"
|
|
6
|
+
import { self } from "./self.ts"
|
|
7
|
+
|
|
8
|
+
export const thread: Effect.Effect<Thread> = Effect.gen(function*() {
|
|
9
|
+
return Thread({
|
|
10
|
+
id: ThreadId.make(crypto.randomUUID()),
|
|
11
|
+
parent: yield* Effect.serviceOption(self),
|
|
12
|
+
events: yield* PubSub.unbounded<LEvent>(),
|
|
13
|
+
state: ThreadState.default(),
|
|
14
|
+
tools: Option.none(),
|
|
15
|
+
})
|
|
16
|
+
})
|
package/L/toolkit.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import * as AiToolkit from "@effect/ai/AiToolkit"
|
|
2
|
+
import * as Effect from "effect/Effect"
|
|
3
|
+
import * as Option from "effect/Option"
|
|
4
|
+
import type { NeverTool } from "../util/NeverTool.ts"
|
|
5
|
+
import { self } from "./self.ts"
|
|
6
|
+
|
|
7
|
+
export const toolkit = self.pipe(
|
|
8
|
+
Effect.flatMap(({ tools }) =>
|
|
9
|
+
Option.match(tools, {
|
|
10
|
+
onSome: (tools) => AiToolkit.make(...tools),
|
|
11
|
+
onNone: () => AiToolkit.make<ReadonlyArray<NeverTool>>(),
|
|
12
|
+
})
|
|
13
|
+
),
|
|
14
|
+
)
|
|
@@ -2,7 +2,8 @@ import { TextPart, UserMessage } from "@effect/ai/AiInput"
|
|
|
2
2
|
import { expect, it } from "@effect/vitest"
|
|
3
3
|
import * as Effect from "effect/Effect"
|
|
4
4
|
import { messages } from "./messages.ts"
|
|
5
|
-
import {
|
|
5
|
+
import { provide } from "./provide.ts"
|
|
6
|
+
import { thread } from "./thread.ts"
|
|
6
7
|
import { user } from "./user.ts"
|
|
7
8
|
|
|
8
9
|
it.effect("test success", () =>
|
|
@@ -26,5 +27,7 @@ it.effect("test success", () =>
|
|
|
26
27
|
}),
|
|
27
28
|
])
|
|
28
29
|
}).pipe(
|
|
29
|
-
|
|
30
|
+
provide(
|
|
31
|
+
thread,
|
|
32
|
+
),
|
|
30
33
|
))
|
package/L/user.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { TextPart, UserMessage } from "@effect/ai/AiInput"
|
|
2
|
+
import * as Effect from "effect/Effect"
|
|
3
|
+
import type { Thread } from "../Thread.ts"
|
|
4
|
+
import type { ExtractE, ExtractR } from "../util/extract.ts"
|
|
5
|
+
import { normalize, type TaggableArg0, type TaggableArgRest } from "../util/Taggable.ts"
|
|
6
|
+
import { append } from "./append.ts"
|
|
7
|
+
|
|
8
|
+
/** Append a user message to the thread. */
|
|
9
|
+
export const user = <
|
|
10
|
+
A0 extends TaggableArg0,
|
|
11
|
+
ARest extends TaggableArgRest<A0>,
|
|
12
|
+
>(
|
|
13
|
+
a0: A0,
|
|
14
|
+
...aRest: ARest
|
|
15
|
+
): Effect.Effect<
|
|
16
|
+
void,
|
|
17
|
+
ExtractE<A0 | ARest[number]>,
|
|
18
|
+
ExtractR<A0 | ARest[number]> | Thread
|
|
19
|
+
> =>
|
|
20
|
+
normalize(a0, ...aRest).pipe(
|
|
21
|
+
Effect.flatMap((text) =>
|
|
22
|
+
text
|
|
23
|
+
? append(
|
|
24
|
+
UserMessage.make({
|
|
25
|
+
parts: [
|
|
26
|
+
TextPart.make({ text }),
|
|
27
|
+
],
|
|
28
|
+
}),
|
|
29
|
+
)
|
|
30
|
+
: Effect.succeed(undefined)
|
|
31
|
+
),
|
|
32
|
+
)
|
package/LEvent.ts
CHANGED
|
@@ -1,23 +1,33 @@
|
|
|
1
1
|
import { Message } from "@effect/ai/AiInput"
|
|
2
2
|
import * as Schema from "effect/Schema"
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
export class MessagesAppended extends Schema.TaggedClass<MessagesAppended>("MessagesAppended")("MessagesAppended", {
|
|
8
|
-
messages: Messages,
|
|
4
|
+
/** Event in which the thread's system is set to a new string. */
|
|
5
|
+
export class SystemSetEvent extends Schema.TaggedClass<SystemSetEvent>("SystemSetEvent")("system_set", {
|
|
6
|
+
system: Schema.Option(Schema.String),
|
|
9
7
|
}) {}
|
|
10
8
|
|
|
11
|
-
/**
|
|
12
|
-
export class
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
/** Event in which one or more messages were added to the thread. */
|
|
10
|
+
export class MessagesAppendedEvent
|
|
11
|
+
extends Schema.TaggedClass<MessagesAppendedEvent>("MessagesAppendedEvent")("messages_appended", {
|
|
12
|
+
messages: Schema.Array(Message),
|
|
13
|
+
})
|
|
14
|
+
{}
|
|
15
|
+
|
|
16
|
+
/** Event in which the thread is cleared of messages. */
|
|
17
|
+
export class ThreadClearedEvent
|
|
18
|
+
extends Schema.TaggedClass<ThreadClearedEvent>("MessagesClearedEvent")("messages_cleared", {})
|
|
19
|
+
{}
|
|
15
20
|
|
|
16
21
|
export type LEvent = typeof LEvent["Type"]
|
|
17
22
|
export const LEvent: Schema.Union<[
|
|
18
|
-
typeof
|
|
19
|
-
typeof
|
|
23
|
+
typeof SystemSetEvent,
|
|
24
|
+
typeof MessagesAppendedEvent,
|
|
25
|
+
typeof ThreadClearedEvent,
|
|
20
26
|
]> = Schema.Union(
|
|
21
|
-
|
|
22
|
-
|
|
27
|
+
SystemSetEvent,
|
|
28
|
+
MessagesAppendedEvent,
|
|
29
|
+
ThreadClearedEvent,
|
|
23
30
|
)
|
|
31
|
+
|
|
32
|
+
export const encodeLEvent = Schema.encode(LEvent)
|
|
33
|
+
export const decodeLEvent = Schema.decode(LEvent)
|