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.
Files changed (80) hide show
  1. package/README.md +1 -1
  2. package/dist/AssistantEvent.d.ts +3 -66
  3. package/dist/AssistantEvent.d.ts.map +1 -1
  4. package/dist/AssistantEvent.js +1 -51
  5. package/dist/AssistantEvent.js.map +1 -1
  6. package/dist/AssistantLoop.d.ts +7 -5
  7. package/dist/AssistantLoop.d.ts.map +1 -1
  8. package/dist/AssistantLoop.js +6 -3
  9. package/dist/AssistantLoop.js.map +1 -1
  10. package/dist/Block.js.map +1 -1
  11. package/dist/BlockKit.d.ts +11 -15
  12. package/dist/BlockKit.d.ts.map +1 -1
  13. package/dist/BlockKit.js +3 -6
  14. package/dist/BlockKit.js.map +1 -1
  15. package/dist/ChatView.d.ts +7 -58
  16. package/dist/ChatView.d.ts.map +1 -1
  17. package/dist/ChatView.js +15 -68
  18. package/dist/ChatView.js.map +1 -1
  19. package/dist/Compaction.d.ts +2 -2
  20. package/dist/Compaction.d.ts.map +1 -1
  21. package/dist/Compaction.js +6 -13
  22. package/dist/Compaction.js.map +1 -1
  23. package/dist/ToolDiscovery.d.ts +4 -5
  24. package/dist/ToolDiscovery.d.ts.map +1 -1
  25. package/dist/ToolDiscovery.js +5 -4
  26. package/dist/ToolDiscovery.js.map +1 -1
  27. package/dist/ToolFailure.d.ts +1 -1
  28. package/dist/ToolFailure.js +1 -1
  29. package/dist/ToolFailure.js.map +1 -1
  30. package/dist/index.d.ts +1 -3
  31. package/dist/index.js +3 -5
  32. package/dist/internal/chat.js +6 -31
  33. package/dist/internal/chat.js.map +1 -1
  34. package/dist/internal/history.js +2 -40
  35. package/dist/internal/history.js.map +1 -1
  36. package/dist/internal/loop.d.ts +2 -2
  37. package/dist/internal/loop.d.ts.map +1 -1
  38. package/dist/internal/loop.js +20 -55
  39. package/dist/internal/loop.js.map +1 -1
  40. package/dist/internal/specialists.js +2 -3
  41. package/dist/internal/specialists.js.map +1 -1
  42. package/dist/internal/toolkit.d.ts +6 -20
  43. package/dist/internal/toolkit.d.ts.map +1 -1
  44. package/dist/internal/toolkit.js +10 -31
  45. package/dist/internal/toolkit.js.map +1 -1
  46. package/dist/internal/tools.js +1 -20
  47. package/dist/internal/tools.js.map +1 -1
  48. package/dist/internal/turns.d.ts.map +1 -1
  49. package/dist/internal/turns.js +2 -9
  50. package/dist/internal/turns.js.map +1 -1
  51. package/package.json +3 -2
  52. package/src/AssistantEvent.ts +0 -66
  53. package/src/AssistantLoop.ts +7 -5
  54. package/src/Block.ts +1 -1
  55. package/src/BlockKit.ts +12 -25
  56. package/src/ChatView.ts +10 -81
  57. package/src/Compaction.ts +2 -19
  58. package/src/ToolDiscovery.ts +5 -13
  59. package/src/ToolFailure.ts +1 -1
  60. package/src/index.ts +0 -10
  61. package/src/internal/chat.ts +4 -53
  62. package/src/internal/history.ts +2 -74
  63. package/src/internal/loop.ts +31 -101
  64. package/src/internal/specialists.ts +3 -7
  65. package/src/internal/toolkit.ts +17 -60
  66. package/src/internal/tools.ts +2 -53
  67. package/src/internal/turns.ts +7 -26
  68. package/dist/Decision.d.ts +0 -145
  69. package/dist/Decision.d.ts.map +0 -1
  70. package/dist/Decision.js +0 -178
  71. package/dist/Decision.js.map +0 -1
  72. package/dist/DecisionId.d.ts +0 -37
  73. package/dist/DecisionId.d.ts.map +0 -1
  74. package/dist/DecisionId.js +0 -44
  75. package/dist/DecisionId.js.map +0 -1
  76. package/dist/internal/decisions.js +0 -66
  77. package/dist/internal/decisions.js.map +0 -1
  78. package/src/Decision.ts +0 -241
  79. package/src/DecisionId.ts +0 -46
  80. 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
- )