@statelyai/agent 1.1.6 → 2.0.0-alpha.6
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/LICENSE +21 -0
- package/dist/ai-sdk.cjs +249 -0
- package/dist/ai-sdk.d.cts +168 -0
- package/dist/ai-sdk.d.mts +168 -0
- package/dist/ai-sdk.mjs +241 -0
- package/dist/cli.cjs +63 -0
- package/dist/cli.d.cts +1 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.mjs +64 -0
- package/dist/decision-CX3YdwrO.cjs +1239 -0
- package/dist/decision-D1654JdD.mjs +940 -0
- package/dist/index.cjs +54 -0
- package/dist/index.d.cts +1217 -0
- package/dist/index.d.mts +1194 -405
- package/dist/index.mjs +3 -588
- package/dist/openai-compat.cjs +319 -0
- package/dist/openai-compat.d.cts +98 -0
- package/dist/openai-compat.d.mts +98 -0
- package/dist/openai-compat.mjs +312 -0
- package/dist/src-CEa947Dm.mjs +2449 -0
- package/dist/src-wBfi-kTA.cjs +2568 -0
- package/dist/text-logic-1ZQkO3zr.d.cts +682 -0
- package/dist/text-logic-2EMJIS-n.d.mts +682 -0
- package/dist/types-BHjeDdch.d.cts +208 -0
- package/dist/types-Cq1YlAQ6.d.mts +208 -0
- package/dist/utils-CWUCa3pF.d.mts +108 -0
- package/dist/utils-lK1wnL2i.d.cts +108 -0
- package/dist/zod.cjs +31 -0
- package/dist/zod.d.cts +30 -0
- package/dist/zod.d.mts +30 -0
- package/dist/zod.mjs +30 -0
- package/package.json +109 -28
- package/readme.md +144 -6
- package/schemas/agent-workflow.json +527 -0
- package/.changeset/README.md +0 -8
- package/.changeset/config.json +0 -11
- package/.env.template +0 -3
- package/.github/actions/ci-setup/action.yml +0 -24
- package/.github/workflows/release.yml +0 -46
- package/.vscode/launch.json +0 -28
- package/CHANGELOG.md +0 -222
- package/dist/index.d.ts +0 -428
- package/dist/index.js +0 -621
- package/examples/chatbot.ts +0 -71
- package/examples/cot.ts +0 -89
- package/examples/email.ts +0 -118
- package/examples/example.ts +0 -81
- package/examples/goal.ts +0 -94
- package/examples/helpers/helpers.ts +0 -17
- package/examples/helpers/loader.ts +0 -32
- package/examples/helpers/runner.ts +0 -27
- package/examples/joke.ts +0 -225
- package/examples/multi.ts +0 -103
- package/examples/newspaper.ts +0 -324
- package/examples/number.ts +0 -102
- package/examples/raffle.ts +0 -105
- package/examples/sandbox.ts +0 -28
- package/examples/simple.ts +0 -39
- package/examples/support.ts +0 -147
- package/examples/ticTacToe.ts +0 -224
- package/examples/todo.ts +0 -137
- package/examples/tutor.ts +0 -100
- package/examples/verify.ts +0 -120
- package/examples/weather.ts +0 -178
- package/examples/wiki.ts +0 -30
- package/examples/word.ts +0 -171
- package/src/adapters/vercel.ts +0 -7
- package/src/agent-experimental.ts +0 -221
- package/src/agent.test.ts +0 -506
- package/src/agent.ts +0 -300
- package/src/decision.test.ts +0 -179
- package/src/decision.ts +0 -84
- package/src/index.ts +0 -4
- package/src/memory.ts +0 -25
- package/src/planners/shortestPathPlanner.ts +0 -22
- package/src/planners/simplePlanner.ts +0 -139
- package/src/schemas.ts +0 -11
- package/src/strategies/chain-of-note.ts +0 -155
- package/src/templates/defaultText.ts +0 -18
- package/src/text.ts +0 -241
- package/src/types.ts +0 -499
- package/src/utils.ts +0 -72
- package/tsconfig.json +0 -109
- package/vitest.config.ts +0 -9
|
@@ -1,221 +0,0 @@
|
|
|
1
|
-
// // type AgentExperiences<TState, TReward> = Record<
|
|
2
|
-
// // string, // serialized state
|
|
3
|
-
// // Record<
|
|
4
|
-
// // string, // serialized event
|
|
5
|
-
// // {
|
|
6
|
-
// // state: TState;
|
|
7
|
-
// // reward: TReward;
|
|
8
|
-
// // }
|
|
9
|
-
// // >
|
|
10
|
-
|
|
11
|
-
// import OpenAI from 'openai';
|
|
12
|
-
// import {
|
|
13
|
-
// AnyEventObject,
|
|
14
|
-
// EventObject,
|
|
15
|
-
// AnyActorLogic,
|
|
16
|
-
// AnyMachineSnapshot,
|
|
17
|
-
// ActorRef,
|
|
18
|
-
// AnyActorRef,
|
|
19
|
-
// SnapshotFrom,
|
|
20
|
-
// EventFrom,
|
|
21
|
-
// } from 'xstate';
|
|
22
|
-
// import { getToolCalls } from './adapters/openai';
|
|
23
|
-
// import { ZodEventMapping } from './schemas';
|
|
24
|
-
|
|
25
|
-
// // >;
|
|
26
|
-
// interface AgentExperience<TState, TEvent extends AnyEventObject> {
|
|
27
|
-
// prevState: TState | undefined;
|
|
28
|
-
// event: TEvent;
|
|
29
|
-
// nextState: TState;
|
|
30
|
-
// }
|
|
31
|
-
|
|
32
|
-
// type AgentPlan<TState, TEvent extends EventObject> = Array<{
|
|
33
|
-
// /**
|
|
34
|
-
// * The current state
|
|
35
|
-
// */
|
|
36
|
-
// state: TState;
|
|
37
|
-
// /**
|
|
38
|
-
// * The event to execute
|
|
39
|
-
// */
|
|
40
|
-
// event: TEvent;
|
|
41
|
-
// /**
|
|
42
|
-
// * The expected next state
|
|
43
|
-
// */
|
|
44
|
-
// nextState?: TState;
|
|
45
|
-
// }>;
|
|
46
|
-
|
|
47
|
-
// interface AgentModel<
|
|
48
|
-
// // TLogic extends AnyActorLogic,
|
|
49
|
-
// TReward,
|
|
50
|
-
// TState,
|
|
51
|
-
// TEvent extends EventObject
|
|
52
|
-
// > {
|
|
53
|
-
// // policy: ({
|
|
54
|
-
// // logic,
|
|
55
|
-
// // state,
|
|
56
|
-
// // goal,
|
|
57
|
-
// // }: {
|
|
58
|
-
// // logic: TLogic;
|
|
59
|
-
// // state: TState;
|
|
60
|
-
// // goal: string;
|
|
61
|
-
// // }) => Promise<AgentPlan<TState>>;
|
|
62
|
-
// getExperiences: () => Promise<Array<AgentExperience<TState, TEvent>>>; // TODO: TLogic instead?
|
|
63
|
-
// addExperience: (experience: AgentExperience<TState, TEvent>) => void;
|
|
64
|
-
// getLogic: ({
|
|
65
|
-
// experiences,
|
|
66
|
-
// }: {
|
|
67
|
-
// experiences: Array<AgentExperience<TState, TEvent>>; // TODO: TLogic instead?
|
|
68
|
-
// }) => Promise<AnyActorLogic>;
|
|
69
|
-
// getNextEvents: ({
|
|
70
|
-
// logic,
|
|
71
|
-
// state,
|
|
72
|
-
// }: {
|
|
73
|
-
// logic: AnyActorLogic;
|
|
74
|
-
// state: TState;
|
|
75
|
-
// }) => Promise<AnyEventObject[]>;
|
|
76
|
-
// getPlans: ({
|
|
77
|
-
// logic,
|
|
78
|
-
// state,
|
|
79
|
-
// goals,
|
|
80
|
-
// }: {
|
|
81
|
-
// logic: AnyActorLogic;
|
|
82
|
-
// state: TState;
|
|
83
|
-
// goals: string[];
|
|
84
|
-
// }) => Promise<Array<AgentPlan<TState, TEvent>>>;
|
|
85
|
-
// getReward: ({
|
|
86
|
-
// logic,
|
|
87
|
-
// state,
|
|
88
|
-
// goals,
|
|
89
|
-
// action,
|
|
90
|
-
// }: {
|
|
91
|
-
// logic: AnyActorLogic;
|
|
92
|
-
// state: TState;
|
|
93
|
-
// goals: string[];
|
|
94
|
-
// action: EventObject;
|
|
95
|
-
// }) => Promise<TReward>;
|
|
96
|
-
// }
|
|
97
|
-
|
|
98
|
-
// interface AgentLogic<T> {
|
|
99
|
-
// /**
|
|
100
|
-
// * The next possible actions (represented by events) that the agent can take
|
|
101
|
-
// * based on the current state of the environment
|
|
102
|
-
// */
|
|
103
|
-
// getActions(state: T): Promise<AnyEventObject[]>;
|
|
104
|
-
// getPlan(state: T, goal: any): Promise<Array<[T, EventObject]>>;
|
|
105
|
-
// }
|
|
106
|
-
|
|
107
|
-
// interface Agent<TState extends AnyMachineSnapshot, TEvent extends EventObject> {
|
|
108
|
-
// act: (env: ActorRef<TState, TEvent>) => Promise<void>;
|
|
109
|
-
// }
|
|
110
|
-
|
|
111
|
-
// function createAgent2<TEnvironment extends AnyActorRef>(
|
|
112
|
-
// openai: OpenAI,
|
|
113
|
-
// // logic: AnyActorLogic,
|
|
114
|
-
// // input: InputFrom<TLogic>,
|
|
115
|
-
// getGoals: (state: SnapshotFrom<TEnvironment>) => string | string[],
|
|
116
|
-
// schemas: ZodEventMapping
|
|
117
|
-
// ): Agent<SnapshotFrom<TEnvironment>, EventFrom<TEnvironment>> {
|
|
118
|
-
// const experiences: Array<AgentExperience<any, any>> = [];
|
|
119
|
-
|
|
120
|
-
// const agentModel: AgentModel<
|
|
121
|
-
// any,
|
|
122
|
-
// SnapshotFrom<TEnvironment>,
|
|
123
|
-
// EventFrom<TEnvironment>
|
|
124
|
-
// > = {
|
|
125
|
-
// // policy: async ({ logic, state, goal }) => {
|
|
126
|
-
// // const toolEvents = await getToolCalls(
|
|
127
|
-
// // openai,
|
|
128
|
-
// // goal,
|
|
129
|
-
// // state,
|
|
130
|
-
// // 'gpt-4-1106-preview',
|
|
131
|
-
// // (eventType) => eventType.startsWith('agent.'),
|
|
132
|
-
// // schemas
|
|
133
|
-
// // );
|
|
134
|
-
// // console.log(toolEvents);
|
|
135
|
-
// // return toolEvents.map((te) => ({
|
|
136
|
-
// // state,
|
|
137
|
-
// // event: te as EventFromLogic<TLogic>,
|
|
138
|
-
// // }));
|
|
139
|
-
// // },
|
|
140
|
-
// addExperience: (experience) => {
|
|
141
|
-
// experiences.push(experience);
|
|
142
|
-
// },
|
|
143
|
-
// getExperiences: async () => experiences,
|
|
144
|
-
// getLogic: async ({ experiences }) => {
|
|
145
|
-
// return null as any; // TODO
|
|
146
|
-
// },
|
|
147
|
-
// getNextEvents: async ({ logic, state }) => {
|
|
148
|
-
// return [];
|
|
149
|
-
// },
|
|
150
|
-
// getReward: async ({ logic, state, goals, action }) => {
|
|
151
|
-
// return 0;
|
|
152
|
-
// },
|
|
153
|
-
// getPlans: async ({ logic, state, goals }) => {
|
|
154
|
-
// if (!goals[0]) {
|
|
155
|
-
// return [];
|
|
156
|
-
// }
|
|
157
|
-
|
|
158
|
-
// const toolEvents = await getToolCalls(
|
|
159
|
-
// openai,
|
|
160
|
-
// goals[0] + '\nOnly make a single tool call.',
|
|
161
|
-
// state as any,
|
|
162
|
-
// 'gpt-3.5-turbo-16k-0613',
|
|
163
|
-
// (eventType) => eventType.startsWith('agent.'),
|
|
164
|
-
// schemas
|
|
165
|
-
// );
|
|
166
|
-
|
|
167
|
-
// console.log(toolEvents);
|
|
168
|
-
|
|
169
|
-
// return [
|
|
170
|
-
// toolEvents.map((toolEvent) => ({
|
|
171
|
-
// state,
|
|
172
|
-
// event: toolEvent as EventFrom<TEnvironment>,
|
|
173
|
-
// })),
|
|
174
|
-
// ];
|
|
175
|
-
// },
|
|
176
|
-
// };
|
|
177
|
-
|
|
178
|
-
// // const actor = createActor(logic, {
|
|
179
|
-
// // input,
|
|
180
|
-
// // inspect: (inspEv) => {
|
|
181
|
-
// // if (inspEv.type === '@xstate.snapshot') {
|
|
182
|
-
// // agentModel.addExperience({
|
|
183
|
-
// // prevState: experiences[experiences.length - 1]?.nextState,
|
|
184
|
-
// // nextState: (inspEv.snapshot as AnyMachineSnapshot).value,
|
|
185
|
-
// // event: inspEv.event as EventFromLogic<TLogic>,
|
|
186
|
-
// // });
|
|
187
|
-
// // }
|
|
188
|
-
// // },
|
|
189
|
-
// // });
|
|
190
|
-
|
|
191
|
-
// return {
|
|
192
|
-
// act: async (actorRef) => {
|
|
193
|
-
// const state = actorRef.getSnapshot();
|
|
194
|
-
// // @ts-ignore
|
|
195
|
-
// console.log(state.value, state.context);
|
|
196
|
-
// const experiences = await agentModel.getExperiences();
|
|
197
|
-
// const goals = toArray(getGoals(state));
|
|
198
|
-
// console.log('Goal:', goals);
|
|
199
|
-
|
|
200
|
-
// const nextPlans = await agentModel.getPlans({
|
|
201
|
-
// logic: await agentModel.getLogic({ experiences }),
|
|
202
|
-
// goals,
|
|
203
|
-
// state,
|
|
204
|
-
// });
|
|
205
|
-
|
|
206
|
-
// const nextStep = nextPlans?.[0]?.[0];
|
|
207
|
-
|
|
208
|
-
// // TODO: race conditions!
|
|
209
|
-
// if (nextStep) {
|
|
210
|
-
// console.log('nextStep', nextStep?.event);
|
|
211
|
-
// actorRef.send(nextStep.event);
|
|
212
|
-
// } else {
|
|
213
|
-
// console.log('No next step');
|
|
214
|
-
// }
|
|
215
|
-
// },
|
|
216
|
-
// } satisfies Agent<SnapshotFrom<TEnvironment>, EventFrom<TEnvironment>>; // TODO: fix types
|
|
217
|
-
// }
|
|
218
|
-
|
|
219
|
-
// function toArray<T>(value: T | T[]): T[] {
|
|
220
|
-
// return Array.isArray(value) ? value : [value];
|
|
221
|
-
// }
|
package/src/agent.test.ts
DELETED
|
@@ -1,506 +0,0 @@
|
|
|
1
|
-
import { test, expect, vi } from 'vitest';
|
|
2
|
-
import {
|
|
3
|
-
AgentGenerateTextResult,
|
|
4
|
-
AgentMessage,
|
|
5
|
-
createAgent,
|
|
6
|
-
type AIAdapter,
|
|
7
|
-
} from './';
|
|
8
|
-
import { createActor, createMachine } from 'xstate';
|
|
9
|
-
import { GenerateTextResult } from 'ai';
|
|
10
|
-
import { z } from 'zod';
|
|
11
|
-
|
|
12
|
-
test('an agent has the expected interface', () => {
|
|
13
|
-
const agent = createAgent({
|
|
14
|
-
name: 'test',
|
|
15
|
-
events: {},
|
|
16
|
-
model: {} as any,
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
expect(agent.decide).toBeDefined();
|
|
20
|
-
expect(agent.generateText).toBeDefined();
|
|
21
|
-
expect(agent.streamText).toBeDefined();
|
|
22
|
-
|
|
23
|
-
expect(agent.addMessage).toBeDefined();
|
|
24
|
-
expect(agent.addObservation).toBeDefined();
|
|
25
|
-
expect(agent.addFeedback).toBeDefined();
|
|
26
|
-
expect(agent.addPlan).toBeDefined();
|
|
27
|
-
|
|
28
|
-
expect(agent.getMessages).toBeDefined();
|
|
29
|
-
expect(agent.getObservations).toBeDefined();
|
|
30
|
-
expect(agent.getFeedback).toBeDefined();
|
|
31
|
-
expect(agent.getPlans).toBeDefined();
|
|
32
|
-
|
|
33
|
-
expect(agent.interact).toBeDefined();
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
test('agent.addMessage() adds to message history', () => {
|
|
37
|
-
const agent = createAgent({
|
|
38
|
-
name: 'test',
|
|
39
|
-
events: {},
|
|
40
|
-
model: {} as any,
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
agent.addMessage({
|
|
44
|
-
content: 'msg 1',
|
|
45
|
-
role: 'user',
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
const messageHistory = agent.addMessage({
|
|
49
|
-
content: 'response 1',
|
|
50
|
-
role: 'assistant',
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
expect(messageHistory.sessionId).toEqual(agent.sessionId);
|
|
54
|
-
|
|
55
|
-
expect(agent.select((c) => c.messages)).toContainEqual(
|
|
56
|
-
expect.objectContaining({
|
|
57
|
-
content: 'msg 1',
|
|
58
|
-
})
|
|
59
|
-
);
|
|
60
|
-
expect(agent.getMessages()).toContainEqual(
|
|
61
|
-
expect.objectContaining({
|
|
62
|
-
content: 'msg 1',
|
|
63
|
-
})
|
|
64
|
-
);
|
|
65
|
-
|
|
66
|
-
expect(agent.select((c) => c.messages)).toContainEqual(
|
|
67
|
-
expect.objectContaining({
|
|
68
|
-
content: 'response 1',
|
|
69
|
-
sessionId: expect.any(String),
|
|
70
|
-
timestamp: expect.any(Number),
|
|
71
|
-
})
|
|
72
|
-
);
|
|
73
|
-
expect(agent.getMessages()).toContainEqual(
|
|
74
|
-
expect.objectContaining({
|
|
75
|
-
content: 'response 1',
|
|
76
|
-
sessionId: expect.any(String),
|
|
77
|
-
timestamp: expect.any(Number),
|
|
78
|
-
})
|
|
79
|
-
);
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
test('agent.addFeedback() adds to feedback', () => {
|
|
83
|
-
const agent = createAgent({
|
|
84
|
-
name: 'test',
|
|
85
|
-
events: {},
|
|
86
|
-
model: {} as any,
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
const feedback = agent.addFeedback({
|
|
90
|
-
attributes: {
|
|
91
|
-
score: -1,
|
|
92
|
-
},
|
|
93
|
-
goal: 'Win the game',
|
|
94
|
-
observationId: 'obs-1',
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
expect(feedback.sessionId).toEqual(agent.sessionId);
|
|
98
|
-
|
|
99
|
-
expect(agent.select((c) => c.feedback)).toContainEqual(
|
|
100
|
-
expect.objectContaining({
|
|
101
|
-
attributes: {
|
|
102
|
-
score: -1,
|
|
103
|
-
},
|
|
104
|
-
goal: 'Win the game',
|
|
105
|
-
observationId: 'obs-1',
|
|
106
|
-
sessionId: expect.any(String),
|
|
107
|
-
timestamp: expect.any(Number),
|
|
108
|
-
})
|
|
109
|
-
);
|
|
110
|
-
expect(agent.getFeedback()).toContainEqual(
|
|
111
|
-
expect.objectContaining({
|
|
112
|
-
attributes: {
|
|
113
|
-
score: -1,
|
|
114
|
-
},
|
|
115
|
-
goal: 'Win the game',
|
|
116
|
-
observationId: 'obs-1',
|
|
117
|
-
sessionId: expect.any(String),
|
|
118
|
-
timestamp: expect.any(Number),
|
|
119
|
-
})
|
|
120
|
-
);
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
test('agent.addObservation() adds to observations', () => {
|
|
124
|
-
const agent = createAgent({
|
|
125
|
-
name: 'test',
|
|
126
|
-
events: {},
|
|
127
|
-
model: {} as any,
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
const observation = agent.addObservation({
|
|
131
|
-
prevState: { value: 'playing', context: {} },
|
|
132
|
-
event: { type: 'play', position: 3 },
|
|
133
|
-
state: { value: 'lost', context: {} },
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
expect(observation.sessionId).toEqual(agent.sessionId);
|
|
137
|
-
|
|
138
|
-
expect(agent.select((c) => c.observations)).toContainEqual(
|
|
139
|
-
expect.objectContaining({
|
|
140
|
-
prevState: { value: 'playing', context: {} },
|
|
141
|
-
event: { type: 'play', position: 3 },
|
|
142
|
-
state: { value: 'lost', context: {} },
|
|
143
|
-
sessionId: expect.any(String),
|
|
144
|
-
timestamp: expect.any(Number),
|
|
145
|
-
})
|
|
146
|
-
);
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
test('agent.addObservation() adds to observations with machine hash', () => {
|
|
150
|
-
const agent = createAgent({
|
|
151
|
-
name: 'test',
|
|
152
|
-
events: {},
|
|
153
|
-
model: {} as any,
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
const machine = createMachine({
|
|
157
|
-
initial: 'playing',
|
|
158
|
-
states: {
|
|
159
|
-
playing: {
|
|
160
|
-
on: {
|
|
161
|
-
play: 'lost',
|
|
162
|
-
},
|
|
163
|
-
},
|
|
164
|
-
lost: {},
|
|
165
|
-
},
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
const observation = agent.addObservation({
|
|
169
|
-
prevState: { value: 'playing', context: {} },
|
|
170
|
-
event: { type: 'play', position: 3 },
|
|
171
|
-
state: { value: 'lost', context: {} },
|
|
172
|
-
machine,
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
expect(observation.sessionId).toEqual(agent.sessionId);
|
|
176
|
-
|
|
177
|
-
expect(agent.select((c) => c.observations)).toContainEqual(
|
|
178
|
-
expect.objectContaining({
|
|
179
|
-
prevState: { value: 'playing', context: {} },
|
|
180
|
-
event: { type: 'play', position: 3 },
|
|
181
|
-
state: { value: 'lost', context: {} },
|
|
182
|
-
machineHash: expect.any(String),
|
|
183
|
-
sessionId: expect.any(String),
|
|
184
|
-
timestamp: expect.any(Number),
|
|
185
|
-
})
|
|
186
|
-
);
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
test('agent.interact() observes machine actors (no 2nd arg)', () => {
|
|
190
|
-
const machine = createMachine({
|
|
191
|
-
initial: 'a',
|
|
192
|
-
states: {
|
|
193
|
-
a: {
|
|
194
|
-
on: { NEXT: 'b' },
|
|
195
|
-
},
|
|
196
|
-
b: {},
|
|
197
|
-
},
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
const agent = createAgent({
|
|
201
|
-
name: 'test',
|
|
202
|
-
events: {},
|
|
203
|
-
model: {} as any,
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
const actor = createActor(machine);
|
|
207
|
-
|
|
208
|
-
agent.interact(actor);
|
|
209
|
-
|
|
210
|
-
actor.start();
|
|
211
|
-
|
|
212
|
-
expect(agent.select((c) => c.observations)).toContainEqual(
|
|
213
|
-
expect.objectContaining({
|
|
214
|
-
prevState: undefined,
|
|
215
|
-
state: expect.objectContaining({ value: 'a' }),
|
|
216
|
-
})
|
|
217
|
-
);
|
|
218
|
-
expect(agent.getObservations()).toContainEqual(
|
|
219
|
-
expect.objectContaining({
|
|
220
|
-
prevState: undefined,
|
|
221
|
-
state: expect.objectContaining({ value: 'a' }),
|
|
222
|
-
})
|
|
223
|
-
);
|
|
224
|
-
|
|
225
|
-
actor.send({ type: 'NEXT' });
|
|
226
|
-
|
|
227
|
-
expect(agent.select((c) => c.observations)).toContainEqual(
|
|
228
|
-
expect.objectContaining({
|
|
229
|
-
prevState: expect.objectContaining({ value: 'a' }),
|
|
230
|
-
event: { type: 'NEXT' },
|
|
231
|
-
state: expect.objectContaining({ value: 'b' }),
|
|
232
|
-
})
|
|
233
|
-
);
|
|
234
|
-
});
|
|
235
|
-
|
|
236
|
-
test('Agents can use a custom adapter', async () => {
|
|
237
|
-
const adapter = {
|
|
238
|
-
generateText: async () => {
|
|
239
|
-
return {
|
|
240
|
-
text: 'Response',
|
|
241
|
-
} as any;
|
|
242
|
-
},
|
|
243
|
-
} as unknown as AIAdapter;
|
|
244
|
-
|
|
245
|
-
const agent = createAgent({
|
|
246
|
-
name: 'test',
|
|
247
|
-
events: {},
|
|
248
|
-
adapter,
|
|
249
|
-
model: {} as any,
|
|
250
|
-
});
|
|
251
|
-
|
|
252
|
-
const res = await agent.generateText({
|
|
253
|
-
prompt: 'Question?',
|
|
254
|
-
});
|
|
255
|
-
|
|
256
|
-
expect(res.text).toEqual('Response');
|
|
257
|
-
});
|
|
258
|
-
|
|
259
|
-
test('You can listen for feedback events', () => {
|
|
260
|
-
const fn = vi.fn();
|
|
261
|
-
const agent = createAgent({
|
|
262
|
-
name: 'test',
|
|
263
|
-
events: {},
|
|
264
|
-
adapter: {} as any,
|
|
265
|
-
model: {} as any,
|
|
266
|
-
});
|
|
267
|
-
|
|
268
|
-
agent.on('feedback', fn);
|
|
269
|
-
|
|
270
|
-
agent.addFeedback({
|
|
271
|
-
attributes: {
|
|
272
|
-
score: -1,
|
|
273
|
-
},
|
|
274
|
-
goal: 'Win the game',
|
|
275
|
-
observationId: 'obs-1',
|
|
276
|
-
});
|
|
277
|
-
|
|
278
|
-
expect(fn).toHaveBeenCalled();
|
|
279
|
-
});
|
|
280
|
-
|
|
281
|
-
test('You can listen for plan events', async () => {
|
|
282
|
-
const fn = vi.fn();
|
|
283
|
-
const agent = createAgent({
|
|
284
|
-
name: 'test',
|
|
285
|
-
model: {} as any,
|
|
286
|
-
events: {
|
|
287
|
-
WIN: z.object({}),
|
|
288
|
-
},
|
|
289
|
-
adapter: {
|
|
290
|
-
generateText: async (arg) => {
|
|
291
|
-
const keys = Object.keys(arg.tools!);
|
|
292
|
-
|
|
293
|
-
if (keys.length !== 1) {
|
|
294
|
-
throw new Error('Expected only 1 choice');
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
return {
|
|
298
|
-
toolResults: [
|
|
299
|
-
{
|
|
300
|
-
result: {
|
|
301
|
-
type: keys[0],
|
|
302
|
-
},
|
|
303
|
-
},
|
|
304
|
-
],
|
|
305
|
-
} as any as AgentGenerateTextResult;
|
|
306
|
-
},
|
|
307
|
-
streamText: {} as any,
|
|
308
|
-
},
|
|
309
|
-
});
|
|
310
|
-
|
|
311
|
-
agent.on('plan', fn);
|
|
312
|
-
|
|
313
|
-
await agent.decide({
|
|
314
|
-
goal: 'Win the game',
|
|
315
|
-
state: {
|
|
316
|
-
value: 'playing',
|
|
317
|
-
context: {},
|
|
318
|
-
},
|
|
319
|
-
machine: createMachine({
|
|
320
|
-
initial: 'playing',
|
|
321
|
-
states: {
|
|
322
|
-
playing: {
|
|
323
|
-
on: {
|
|
324
|
-
WIN: {
|
|
325
|
-
target: 'won',
|
|
326
|
-
},
|
|
327
|
-
},
|
|
328
|
-
},
|
|
329
|
-
won: {},
|
|
330
|
-
},
|
|
331
|
-
}),
|
|
332
|
-
});
|
|
333
|
-
|
|
334
|
-
expect(fn).toHaveBeenCalledWith(
|
|
335
|
-
expect.objectContaining({
|
|
336
|
-
plan: expect.objectContaining({
|
|
337
|
-
nextEvent: {
|
|
338
|
-
type: 'WIN',
|
|
339
|
-
},
|
|
340
|
-
}),
|
|
341
|
-
})
|
|
342
|
-
);
|
|
343
|
-
});
|
|
344
|
-
|
|
345
|
-
test('agent.types provides context and event types', () => {
|
|
346
|
-
const agent = createAgent({
|
|
347
|
-
model: {} as any,
|
|
348
|
-
events: {
|
|
349
|
-
setScore: z.object({
|
|
350
|
-
score: z.number(),
|
|
351
|
-
}),
|
|
352
|
-
},
|
|
353
|
-
context: {
|
|
354
|
-
score: z.number(),
|
|
355
|
-
},
|
|
356
|
-
});
|
|
357
|
-
|
|
358
|
-
agent.types satisfies { context: any; events: any };
|
|
359
|
-
|
|
360
|
-
agent.types.context satisfies { score: number };
|
|
361
|
-
|
|
362
|
-
// @ts-expect-error
|
|
363
|
-
agent.types.context satisfies { score: string };
|
|
364
|
-
});
|
|
365
|
-
|
|
366
|
-
test.each(['generateText', 'streamText'] as const)(
|
|
367
|
-
'can provide a correlation ID (%s)',
|
|
368
|
-
async (method) => {
|
|
369
|
-
const agent = createAgent({
|
|
370
|
-
model: {} as any,
|
|
371
|
-
events: {},
|
|
372
|
-
adapter: {
|
|
373
|
-
[method]: async (opts: any) => {
|
|
374
|
-
const res = {
|
|
375
|
-
text: 'response',
|
|
376
|
-
};
|
|
377
|
-
|
|
378
|
-
opts.onFinish?.(res);
|
|
379
|
-
|
|
380
|
-
return res as AgentGenerateTextResult;
|
|
381
|
-
},
|
|
382
|
-
} as any as AIAdapter,
|
|
383
|
-
});
|
|
384
|
-
|
|
385
|
-
const promise = new Promise<AgentMessage>((res) => {
|
|
386
|
-
agent.onMessage((msg) => {
|
|
387
|
-
if (msg.role === 'assistant') {
|
|
388
|
-
res(msg);
|
|
389
|
-
}
|
|
390
|
-
});
|
|
391
|
-
});
|
|
392
|
-
|
|
393
|
-
await agent[method]({
|
|
394
|
-
prompt: 'hi',
|
|
395
|
-
correlationId: 'c-1',
|
|
396
|
-
});
|
|
397
|
-
|
|
398
|
-
const msg = await promise;
|
|
399
|
-
|
|
400
|
-
expect(msg.correlationId).toBe('c-1');
|
|
401
|
-
expect(msg.parentCorrelationId).toBe(undefined);
|
|
402
|
-
}
|
|
403
|
-
);
|
|
404
|
-
|
|
405
|
-
test.each(['generateText', 'streamText'] as const)(
|
|
406
|
-
'correlation IDs are automatically generated if not provided (%s)',
|
|
407
|
-
async (method) => {
|
|
408
|
-
const agent = createAgent({
|
|
409
|
-
model: {} as any,
|
|
410
|
-
events: {},
|
|
411
|
-
adapter: {
|
|
412
|
-
[method]: async (opts: any) => {
|
|
413
|
-
const res = {
|
|
414
|
-
text: 'response',
|
|
415
|
-
};
|
|
416
|
-
|
|
417
|
-
opts.onFinish?.(res);
|
|
418
|
-
|
|
419
|
-
return res as AgentGenerateTextResult;
|
|
420
|
-
},
|
|
421
|
-
} as any as AIAdapter,
|
|
422
|
-
});
|
|
423
|
-
|
|
424
|
-
await agent[method]({
|
|
425
|
-
prompt: 'hi',
|
|
426
|
-
});
|
|
427
|
-
|
|
428
|
-
const messages = agent.getMessages();
|
|
429
|
-
|
|
430
|
-
expect(messages[0]?.correlationId).toEqual(expect.stringMatching(/.+/));
|
|
431
|
-
expect(messages[0]?.role).toBe('user');
|
|
432
|
-
expect(messages[1]?.correlationId).toEqual(expect.stringMatching(/.+/));
|
|
433
|
-
expect(messages[1]?.role).toBe('assistant');
|
|
434
|
-
|
|
435
|
-
expect(messages[0]!.correlationId).toEqual(messages[1]!.correlationId);
|
|
436
|
-
}
|
|
437
|
-
);
|
|
438
|
-
|
|
439
|
-
test.each(['generateText', 'streamText'] as const)(
|
|
440
|
-
'can provide a parent correlation ID (%s)',
|
|
441
|
-
async (method) => {
|
|
442
|
-
const agent = createAgent({
|
|
443
|
-
model: {} as any,
|
|
444
|
-
events: {},
|
|
445
|
-
adapter: {
|
|
446
|
-
[method]: async (opts: any) => {
|
|
447
|
-
const res = {
|
|
448
|
-
text: 'response',
|
|
449
|
-
};
|
|
450
|
-
|
|
451
|
-
opts.onFinish?.(res);
|
|
452
|
-
|
|
453
|
-
return res as AgentGenerateTextResult;
|
|
454
|
-
},
|
|
455
|
-
} as any as AIAdapter,
|
|
456
|
-
});
|
|
457
|
-
|
|
458
|
-
await agent[method]({
|
|
459
|
-
prompt: 'hi',
|
|
460
|
-
correlationId: 'c-1',
|
|
461
|
-
parentCorrelationId: 'c-0',
|
|
462
|
-
});
|
|
463
|
-
|
|
464
|
-
const msg = agent.getMessages().find((msg) => msg.role === 'assistant')!;
|
|
465
|
-
|
|
466
|
-
expect(msg.correlationId).toBe('c-1');
|
|
467
|
-
expect(msg.parentCorrelationId).toBe('c-0');
|
|
468
|
-
}
|
|
469
|
-
);
|
|
470
|
-
|
|
471
|
-
test.each(['generateText', 'streamText'] as const)(
|
|
472
|
-
'can add feedback to a correlation (%s)',
|
|
473
|
-
async (method) => {
|
|
474
|
-
const agent = createAgent({
|
|
475
|
-
name: 'test',
|
|
476
|
-
model: {} as any,
|
|
477
|
-
events: {},
|
|
478
|
-
adapter: {
|
|
479
|
-
[method]: async (opts: any) => {
|
|
480
|
-
const res = {
|
|
481
|
-
text: 'response',
|
|
482
|
-
};
|
|
483
|
-
|
|
484
|
-
opts.onFinish?.(res);
|
|
485
|
-
|
|
486
|
-
return res as AgentGenerateTextResult;
|
|
487
|
-
},
|
|
488
|
-
} as any as AIAdapter,
|
|
489
|
-
});
|
|
490
|
-
|
|
491
|
-
const res = await agent[method]({
|
|
492
|
-
prompt: 'test',
|
|
493
|
-
});
|
|
494
|
-
|
|
495
|
-
agent.addFeedback({
|
|
496
|
-
correlationId: res.correlationId,
|
|
497
|
-
reward: -1,
|
|
498
|
-
});
|
|
499
|
-
|
|
500
|
-
const message = agent.getMessages()[0]!;
|
|
501
|
-
const feedback = agent.getFeedback()[0]!;
|
|
502
|
-
|
|
503
|
-
expect(message.correlationId).toBeDefined();
|
|
504
|
-
expect(feedback.correlationId).toEqual(message.correlationId);
|
|
505
|
-
}
|
|
506
|
-
);
|