effect-assistant 0.1.0 → 0.2.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/README.md +1 -1
- package/dist/AssistantEvent.d.ts +3 -66
- package/dist/AssistantEvent.d.ts.map +1 -1
- package/dist/AssistantEvent.js +1 -51
- package/dist/AssistantEvent.js.map +1 -1
- package/dist/AssistantLoop.d.ts +7 -5
- package/dist/AssistantLoop.d.ts.map +1 -1
- package/dist/AssistantLoop.js +6 -3
- package/dist/AssistantLoop.js.map +1 -1
- package/dist/Block.js.map +1 -1
- package/dist/BlockKit.d.ts +11 -15
- package/dist/BlockKit.d.ts.map +1 -1
- package/dist/BlockKit.js +3 -6
- package/dist/BlockKit.js.map +1 -1
- package/dist/ChatView.d.ts +7 -58
- package/dist/ChatView.d.ts.map +1 -1
- package/dist/ChatView.js +15 -68
- package/dist/ChatView.js.map +1 -1
- package/dist/Compaction.d.ts +2 -2
- package/dist/Compaction.d.ts.map +1 -1
- package/dist/Compaction.js +6 -13
- package/dist/Compaction.js.map +1 -1
- package/dist/ToolDiscovery.d.ts +4 -5
- package/dist/ToolDiscovery.d.ts.map +1 -1
- package/dist/ToolDiscovery.js +5 -4
- package/dist/ToolDiscovery.js.map +1 -1
- package/dist/ToolFailure.d.ts +1 -1
- package/dist/ToolFailure.js +1 -1
- package/dist/ToolFailure.js.map +1 -1
- package/dist/index.d.ts +1 -3
- package/dist/index.js +3 -5
- package/dist/internal/chat.js +6 -31
- package/dist/internal/chat.js.map +1 -1
- package/dist/internal/history.js +2 -40
- package/dist/internal/history.js.map +1 -1
- package/dist/internal/loop.d.ts +2 -2
- package/dist/internal/loop.d.ts.map +1 -1
- package/dist/internal/loop.js +20 -55
- package/dist/internal/loop.js.map +1 -1
- package/dist/internal/specialists.js +2 -3
- package/dist/internal/specialists.js.map +1 -1
- package/dist/internal/toolkit.d.ts +6 -20
- package/dist/internal/toolkit.d.ts.map +1 -1
- package/dist/internal/toolkit.js +10 -31
- package/dist/internal/toolkit.js.map +1 -1
- package/dist/internal/tools.js +1 -20
- package/dist/internal/tools.js.map +1 -1
- package/dist/internal/turns.d.ts.map +1 -1
- package/dist/internal/turns.js +2 -9
- package/dist/internal/turns.js.map +1 -1
- package/package.json +3 -2
- package/src/AssistantEvent.ts +0 -66
- package/src/AssistantLoop.ts +7 -5
- package/src/Block.ts +1 -1
- package/src/BlockKit.ts +12 -25
- package/src/ChatView.ts +10 -81
- package/src/Compaction.ts +2 -19
- package/src/ToolDiscovery.ts +5 -13
- package/src/ToolFailure.ts +1 -1
- package/src/index.ts +0 -10
- package/src/internal/chat.ts +4 -53
- package/src/internal/history.ts +2 -74
- package/src/internal/loop.ts +31 -101
- package/src/internal/specialists.ts +3 -7
- package/src/internal/toolkit.ts +17 -60
- package/src/internal/tools.ts +2 -53
- package/src/internal/turns.ts +7 -26
- package/dist/Decision.d.ts +0 -145
- package/dist/Decision.d.ts.map +0 -1
- package/dist/Decision.js +0 -178
- package/dist/Decision.js.map +0 -1
- package/dist/DecisionId.d.ts +0 -37
- package/dist/DecisionId.d.ts.map +0 -1
- package/dist/DecisionId.js +0 -44
- package/dist/DecisionId.js.map +0 -1
- package/dist/internal/decisions.js +0 -66
- package/dist/internal/decisions.js.map +0 -1
- package/src/Decision.ts +0 -241
- package/src/DecisionId.ts +0 -46
- package/src/internal/decisions.ts +0 -131
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
import * as Response from "effect/ai/Response"
|
|
2
|
-
import * as Context from "effect/Context"
|
|
3
|
-
import * as Data from "effect/Data"
|
|
4
|
-
import type * as Effect from "effect/Effect"
|
|
5
|
-
import * as Option from "effect/Option"
|
|
6
|
-
import * as Predicate from "effect/Predicate"
|
|
7
|
-
import * as Schema from "effect/Schema"
|
|
8
|
-
import * as AssistantEvent from "../AssistantEvent.ts"
|
|
9
|
-
import * as BlockKit from "../BlockKit.ts"
|
|
10
|
-
import * as Decision from "../Decision.ts"
|
|
11
|
-
import type { InputId } from "../InputId.ts"
|
|
12
|
-
|
|
13
|
-
// Only a turn's loop parks calls and runs approved ones. A turn's specialists inherit its context, so their runs set
|
|
14
|
-
// it back to none.
|
|
15
|
-
/** @internal */
|
|
16
|
-
export const TurnDecisions = Context.Reference<
|
|
17
|
-
Option.Option<{
|
|
18
|
-
readonly approved: Effect.Effect<ReadonlyArray<AssistantEvent.ToolCallPart>>
|
|
19
|
-
}>
|
|
20
|
-
>("effect-assistant/TurnDecisions", { defaultValue: Option.none })
|
|
21
|
-
|
|
22
|
-
/** @internal */
|
|
23
|
-
export interface Decided {
|
|
24
|
-
readonly request: AssistantEvent.DecisionRequested
|
|
25
|
-
readonly outcome: AssistantEvent.DecisionOutcome
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/** @internal */
|
|
29
|
-
export type Verdict = Data.TaggedEnum<{
|
|
30
|
-
Store: Record<never, never>
|
|
31
|
-
Refuse: { readonly reason: string }
|
|
32
|
-
Decide: { readonly decided: ReadonlyArray<Decided>; readonly answer: InputId }
|
|
33
|
-
}>
|
|
34
|
-
|
|
35
|
-
const Verdicts = Data.taggedEnum<Verdict>()
|
|
36
|
-
|
|
37
|
-
const store = Verdicts.Store()
|
|
38
|
-
|
|
39
|
-
const refuse = (reason: string) => Verdicts.Refuse({ reason })
|
|
40
|
-
|
|
41
|
-
const decodeProps = Schema.decodeUnknownOption(Decision.Props)
|
|
42
|
-
|
|
43
|
-
const decodeAnswer = Schema.decodeUnknownOption(Decision.Answer)
|
|
44
|
-
|
|
45
|
-
const messageOf = (entries: ReadonlyArray<AssistantEvent.AnyEntry>, id: string) =>
|
|
46
|
-
entries
|
|
47
|
-
.map(({ event }) => event)
|
|
48
|
-
.find(
|
|
49
|
-
(event): event is AssistantEvent.AssistantMessage =>
|
|
50
|
-
AssistantEvent.isLibraryEvent(event) && Predicate.isTagged(event, "AssistantMessage") && event.id === id
|
|
51
|
-
)
|
|
52
|
-
|
|
53
|
-
const answerVerdict = (entries: ReadonlyArray<AssistantEvent.AnyEntry>, answer: AssistantEvent.BlockAnswer) => {
|
|
54
|
-
const message = messageOf(entries, answer.messageId)
|
|
55
|
-
const onDecisionBlock = message?.block?.kind === Decision.kind
|
|
56
|
-
|
|
57
|
-
if (!onDecisionBlock && answer.kind !== Decision.kind) return store
|
|
58
|
-
|
|
59
|
-
if (message?.block === undefined || !onDecisionBlock || answer.kind !== Decision.kind) {
|
|
60
|
-
return refuse(`${answer.messageId} has no decision block.`)
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
if (BlockKit.fromEntries(entries).get(message.id)?.open !== true)
|
|
64
|
-
return refuse(`The block on ${message.id} is closed.`)
|
|
65
|
-
|
|
66
|
-
const props = decodeProps(message.block.props)
|
|
67
|
-
const value = decodeAnswer(answer.value)
|
|
68
|
-
|
|
69
|
-
if (Option.isNone(props) || Option.isNone(value)) return refuse(`That isn't an answer to the block on ${message.id}.`)
|
|
70
|
-
|
|
71
|
-
const asked = props.value.decisionIds
|
|
72
|
-
const given = Object.keys(value.value.decisions)
|
|
73
|
-
|
|
74
|
-
if (given.length !== asked.length || !given.every((id) => asked.some((askedId) => askedId === id))) {
|
|
75
|
-
return refuse(`An answer decides exactly the decisions its block asks for: ${asked.join(", ")}.`)
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
const states = Decision.fromEntries(entries)
|
|
79
|
-
const decided: Array<Decided> = []
|
|
80
|
-
|
|
81
|
-
for (const id of asked) {
|
|
82
|
-
const state = states.get(id)
|
|
83
|
-
const outcome = value.value.decisions[id]
|
|
84
|
-
|
|
85
|
-
if (state === undefined || outcome === undefined) return refuse(`No decision ${id}.`)
|
|
86
|
-
|
|
87
|
-
if (state.outcome !== undefined) return refuse(`${id} is already decided.`)
|
|
88
|
-
|
|
89
|
-
decided.push({ request: state.request, outcome })
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
return Verdicts.Decide({ decided, answer: answer.id })
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/** @internal */
|
|
96
|
-
export const verdict = (
|
|
97
|
-
entries: ReadonlyArray<AssistantEvent.AnyEntry>,
|
|
98
|
-
input: AssistantEvent.Input | AssistantEvent.StoredAppEvent
|
|
99
|
-
): Verdict =>
|
|
100
|
-
AssistantEvent.isLibraryEvent(input) && Predicate.isTagged(input, "BlockAnswer")
|
|
101
|
-
? answerVerdict(entries, input)
|
|
102
|
-
: store
|
|
103
|
-
|
|
104
|
-
// A restart can cut the chat off between storing an answer and resolving what it decided.
|
|
105
|
-
/** @internal */
|
|
106
|
-
export const unresolved = (
|
|
107
|
-
entries: ReadonlyArray<AssistantEvent.AnyEntry>
|
|
108
|
-
): ReadonlyArray<Decided & { readonly answer: InputId }> =>
|
|
109
|
-
[...Decision.fromEntries(entries).values()].flatMap((state) =>
|
|
110
|
-
state.outcome !== undefined && state.answer !== undefined && !state.resolved
|
|
111
|
-
? [{ request: state.request, outcome: state.outcome, answer: state.answer }]
|
|
112
|
-
: []
|
|
113
|
-
)
|
|
114
|
-
|
|
115
|
-
// They run with the ids and params the model gave them, before the model's next step.
|
|
116
|
-
/** @internal */
|
|
117
|
-
export const approvedCalls = (
|
|
118
|
-
entries: ReadonlyArray<AssistantEvent.AnyEntry>
|
|
119
|
-
): ReadonlyArray<AssistantEvent.ToolCallPart> =>
|
|
120
|
-
[...Decision.fromEntries(entries).values()].flatMap(({ request, outcome, resolved, result }) =>
|
|
121
|
-
resolved && outcome === "approved" && result === undefined
|
|
122
|
-
? [
|
|
123
|
-
Response.makePart("tool-call", {
|
|
124
|
-
id: request.origin.callId,
|
|
125
|
-
name: request.origin.tool,
|
|
126
|
-
params: request.origin.params,
|
|
127
|
-
providerExecuted: false
|
|
128
|
-
})
|
|
129
|
-
]
|
|
130
|
-
: []
|
|
131
|
-
)
|