@statelyai/agent 1.1.6 → 2.0.0-alpha.10

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 (88) hide show
  1. package/LICENSE +21 -0
  2. package/dist/ai-sdk.cjs +342 -0
  3. package/dist/ai-sdk.d.cts +206 -0
  4. package/dist/ai-sdk.d.mts +206 -0
  5. package/dist/ai-sdk.mjs +331 -0
  6. package/dist/cli.cjs +64 -0
  7. package/dist/cli.d.cts +1 -0
  8. package/dist/cli.d.mts +1 -0
  9. package/dist/cli.mjs +65 -0
  10. package/dist/decision-CQdrKc8k.mjs +978 -0
  11. package/dist/decision-b-lkcs4L.cjs +1295 -0
  12. package/dist/index.cjs +59 -0
  13. package/dist/index.d.cts +212 -0
  14. package/dist/index.d.mts +201 -417
  15. package/dist/index.mjs +4 -588
  16. package/dist/openai-compat.cjs +319 -0
  17. package/dist/openai-compat.d.cts +98 -0
  18. package/dist/openai-compat.d.mts +98 -0
  19. package/dist/openai-compat.mjs +312 -0
  20. package/dist/run-agent-BFMkuI1F.cjs +1599 -0
  21. package/dist/run-agent-BVMd--1l.d.cts +1103 -0
  22. package/dist/run-agent-BoAOq_0Z.mjs +1540 -0
  23. package/dist/run-agent-DzYJb3CK.d.mts +1103 -0
  24. package/dist/src-D-77Ha5p.cjs +1087 -0
  25. package/dist/src-DUeIFjv-.mjs +1016 -0
  26. package/dist/text-logic-C7WJpCIc.d.mts +710 -0
  27. package/dist/text-logic-CZjyACzQ.d.cts +710 -0
  28. package/dist/types-C9QiMjre.d.cts +219 -0
  29. package/dist/types-qm00QF91.d.mts +219 -0
  30. package/dist/utils-Dri7aeEG.d.cts +108 -0
  31. package/dist/utils-Y6GDRGGE.d.mts +108 -0
  32. package/dist/zod.cjs +31 -0
  33. package/dist/zod.d.cts +30 -0
  34. package/dist/zod.d.mts +30 -0
  35. package/dist/zod.mjs +30 -0
  36. package/package.json +109 -28
  37. package/readme.md +143 -6
  38. package/schemas/agent-workflow.json +527 -0
  39. package/.changeset/README.md +0 -8
  40. package/.changeset/config.json +0 -11
  41. package/.env.template +0 -3
  42. package/.github/actions/ci-setup/action.yml +0 -24
  43. package/.github/workflows/release.yml +0 -46
  44. package/.vscode/launch.json +0 -28
  45. package/CHANGELOG.md +0 -222
  46. package/dist/index.d.ts +0 -428
  47. package/dist/index.js +0 -621
  48. package/examples/chatbot.ts +0 -71
  49. package/examples/cot.ts +0 -89
  50. package/examples/email.ts +0 -118
  51. package/examples/example.ts +0 -81
  52. package/examples/goal.ts +0 -94
  53. package/examples/helpers/helpers.ts +0 -17
  54. package/examples/helpers/loader.ts +0 -32
  55. package/examples/helpers/runner.ts +0 -27
  56. package/examples/joke.ts +0 -225
  57. package/examples/multi.ts +0 -103
  58. package/examples/newspaper.ts +0 -324
  59. package/examples/number.ts +0 -102
  60. package/examples/raffle.ts +0 -105
  61. package/examples/sandbox.ts +0 -28
  62. package/examples/simple.ts +0 -39
  63. package/examples/support.ts +0 -147
  64. package/examples/ticTacToe.ts +0 -224
  65. package/examples/todo.ts +0 -137
  66. package/examples/tutor.ts +0 -100
  67. package/examples/verify.ts +0 -120
  68. package/examples/weather.ts +0 -178
  69. package/examples/wiki.ts +0 -30
  70. package/examples/word.ts +0 -171
  71. package/src/adapters/vercel.ts +0 -7
  72. package/src/agent-experimental.ts +0 -221
  73. package/src/agent.test.ts +0 -506
  74. package/src/agent.ts +0 -300
  75. package/src/decision.test.ts +0 -179
  76. package/src/decision.ts +0 -84
  77. package/src/index.ts +0 -4
  78. package/src/memory.ts +0 -25
  79. package/src/planners/shortestPathPlanner.ts +0 -22
  80. package/src/planners/simplePlanner.ts +0 -139
  81. package/src/schemas.ts +0 -11
  82. package/src/strategies/chain-of-note.ts +0 -155
  83. package/src/templates/defaultText.ts +0 -18
  84. package/src/text.ts +0 -241
  85. package/src/types.ts +0 -499
  86. package/src/utils.ts +0 -72
  87. package/tsconfig.json +0 -109
  88. 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
- );