@statelyai/agent 2.0.0-next.1 → 2.0.0-next.2

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 (44) hide show
  1. package/.changeset/grumpy-dolphins-think.md +17 -0
  2. package/.changeset/old-teachers-tap.md +5 -0
  3. package/.changeset/pre.json +4 -1
  4. package/.changeset/smart-yaks-pull.md +23 -0
  5. package/CHANGELOG.md +40 -0
  6. package/dist/index.d.mts +55 -46
  7. package/dist/index.d.ts +55 -46
  8. package/dist/index.js +78 -50
  9. package/dist/index.mjs +81 -53
  10. package/examples/chatbot.ts +2 -2
  11. package/examples/cot.ts +6 -24
  12. package/examples/customer-service-sim.ts +3 -3
  13. package/examples/email.ts +9 -3
  14. package/examples/example.ts +2 -2
  15. package/examples/goal.ts +2 -2
  16. package/examples/joke.ts +2 -2
  17. package/examples/jugs.ts +4 -7
  18. package/examples/learn-from-feedback.ts +100 -0
  19. package/examples/number.ts +2 -2
  20. package/examples/raffle.ts +2 -2
  21. package/examples/river-crossing.ts +4 -7
  22. package/examples/simple.ts +13 -10
  23. package/examples/summary.ts +2 -5
  24. package/examples/support.ts +42 -38
  25. package/examples/ticTacToe.ts +46 -4
  26. package/examples/todo.ts +2 -2
  27. package/examples/tutor.ts +2 -2
  28. package/examples/verify.ts +2 -2
  29. package/examples/weather-agent.ts +141 -0
  30. package/examples/weather.ts +23 -23
  31. package/examples/word.ts +8 -6
  32. package/package.json +2 -1
  33. package/src/agent.test.ts +17 -15
  34. package/src/agent.ts +48 -35
  35. package/src/decide.test.ts +56 -8
  36. package/src/decide.ts +34 -24
  37. package/src/strategies/chainOfThought.ts +48 -0
  38. package/src/{planners → strategies}/shortestPath.test.ts +4 -7
  39. package/src/strategies/shortestPath.ts +173 -0
  40. package/src/{planners → strategies}/simple.ts +28 -18
  41. package/src/types.ts +62 -28
  42. package/src/utils.ts +12 -0
  43. package/src/planners/shortestPath.ts +0 -177
  44. package/src/strategies/chain-of-note.ts +0 -106
package/src/agent.test.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { test, expect, vi } from 'vitest';
2
- import { createAgent } from './';
2
+ import { createAgent, TypesFromAgent } from './';
3
3
  import { createActor, createMachine } from 'xstate';
4
4
  import { LanguageModelV1CallOptions } from 'ai';
5
5
  import { z } from 'zod';
@@ -17,12 +17,12 @@ test('an agent has the expected interface', () => {
17
17
  expect(agent.addMessage).toBeDefined();
18
18
  expect(agent.addObservation).toBeDefined();
19
19
  expect(agent.addFeedback).toBeDefined();
20
- expect(agent.addPlan).toBeDefined();
20
+ expect(agent.addDecision).toBeDefined();
21
21
 
22
22
  expect(agent.getMessages).toBeDefined();
23
23
  expect(agent.getObservations).toBeDefined();
24
24
  expect(agent.getFeedback).toBeDefined();
25
- expect(agent.getPlans).toBeDefined();
25
+ expect(agent.getDecisions).toBeDefined();
26
26
 
27
27
  expect(agent.interact).toBeDefined();
28
28
  });
@@ -307,7 +307,7 @@ test('You can listen for feedback events', () => {
307
307
  expect(fn).toHaveBeenCalled();
308
308
  });
309
309
 
310
- test('You can listen for plan events', async () => {
310
+ test('You can listen for decision events', async () => {
311
311
  const fn = vi.fn();
312
312
  const model = new MockLanguageModelV1({
313
313
  doGenerate: async (params: LanguageModelV1CallOptions) => {
@@ -339,7 +339,7 @@ test('You can listen for plan events', async () => {
339
339
  },
340
340
  });
341
341
 
342
- agent.on('plan', fn);
342
+ agent.on('decision', fn);
343
343
 
344
344
  await agent.decide({
345
345
  goal: 'Win the game',
@@ -364,7 +364,7 @@ test('You can listen for plan events', async () => {
364
364
 
365
365
  expect(fn).toHaveBeenCalledWith(
366
366
  expect.objectContaining({
367
- plan: expect.objectContaining({
367
+ decision: expect.objectContaining({
368
368
  nextEvent: {
369
369
  type: 'WIN',
370
370
  },
@@ -386,12 +386,14 @@ test('agent.types provides context and event types', () => {
386
386
  },
387
387
  });
388
388
 
389
- agent.types satisfies { context: any; events: any };
389
+ let types = {} as TypesFromAgent<typeof agent>;
390
390
 
391
- agent.types.context satisfies { score: number };
391
+ types satisfies { context: any; events: any };
392
+
393
+ types.context satisfies { score: number };
392
394
 
393
395
  // @ts-expect-error
394
- agent.types.context satisfies { score: string };
396
+ types.context satisfies { score: string };
395
397
  });
396
398
 
397
399
  test('It allows unrecognized events', () => {
@@ -436,15 +438,15 @@ test('You can listen for message events', () => {
436
438
  );
437
439
  });
438
440
 
439
- test('agent.getPlans() returns plans from context', () => {
441
+ test('agent.getDecisions() returns decisions from context', () => {
440
442
  const agent = createAgent({
441
443
  id: 'test',
442
444
  events: {},
443
445
  model: {} as any,
444
- planner: async (agent) => {
446
+ strategy: async (agent) => {
445
447
  return {
446
448
  episodeId: agent.episodeId,
447
- planner: 'test-planner',
449
+ strategy: 'test-strategy',
448
450
  goal: '',
449
451
  goalState: undefined,
450
452
  paths: [
@@ -459,10 +461,10 @@ test('agent.getPlans() returns plans from context', () => {
459
461
  },
460
462
  });
461
463
 
462
- const plans = agent.getPlans();
464
+ const decisions = agent.getDecisions();
463
465
 
464
- expect(plans).toBeDefined();
465
- expect(Array.isArray(plans)).toBe(true);
466
+ expect(decisions).toBeDefined();
467
+ expect(Array.isArray(decisions)).toBe(true);
466
468
  });
467
469
 
468
470
  test('Event listeners can be unsubscribed', () => {
package/src/agent.ts CHANGED
@@ -2,7 +2,6 @@ import {
2
2
  Actor,
3
3
  ActorRefLike,
4
4
  AnyEventObject,
5
- AnyStateMachine,
6
5
  EventObject,
7
6
  fromTransition,
8
7
  Subscription,
@@ -11,7 +10,7 @@ import { ZodContextMapping, ZodEventMapping } from './schemas';
11
10
  import {
12
11
  AgentLogic,
13
12
  AgentMessage,
14
- AgentPlanner,
13
+ AgentStrategy,
15
14
  EventsFromZodEventMapping,
16
15
  GenerateTextOptions,
17
16
  AgentLongTermMemory,
@@ -23,13 +22,15 @@ import {
23
22
  AgentFeedback,
24
23
  AgentMessageInput,
25
24
  AgentFeedbackInput,
26
- AgentPlan,
25
+ AgentDecision,
27
26
  Compute,
28
27
  AgentDecisionInput,
29
28
  AgentDecideOptions,
30
29
  AnyAgent,
30
+ EventsFromAgent,
31
+ AgentInteractInput,
31
32
  } from './types';
32
- import { simplePlanner } from './planners/simple';
33
+ import { simpleStrategy } from './strategies/simple';
33
34
  import { agentDecide } from './decide';
34
35
  import { getMachineHash, isActorRef, isMachineActor, randomId } from './utils';
35
36
  import {
@@ -69,12 +70,11 @@ export const agentLogic: AgentLogic<AnyEventObject> = fromTransition(
69
70
  });
70
71
  break;
71
72
  }
72
- case 'agent.plan': {
73
- state.plans.push(event.plan);
73
+ case 'agent.decision': {
74
+ state.decisions.push(event.decision);
74
75
  emit({
75
- type: 'plan',
76
- // @ts-ignore TODO: fix types in XState
77
- plan: event.plan,
76
+ type: 'decision',
77
+ decision: event.decision,
78
78
  });
79
79
  break;
80
80
  }
@@ -91,7 +91,7 @@ export const agentLogic: AgentLogic<AnyEventObject> = fromTransition(
91
91
  feedback: [],
92
92
  messages: [],
93
93
  observations: [],
94
- plans: [],
94
+ decisions: [],
95
95
  } as AgentMemoryContext)
96
96
  );
97
97
 
@@ -106,7 +106,8 @@ export function createAgent<
106
106
  model,
107
107
  events,
108
108
  context,
109
- planner = simplePlanner as AgentPlanner<Agent<TContextSchema, TEventSchemas>>,
109
+ episodeId,
110
+ strategy = simpleStrategy,
110
111
  logic = agentLogic as AgentLogic<TEvents>,
111
112
  }: {
112
113
  /**
@@ -134,7 +135,7 @@ export function createAgent<
134
135
  */
135
136
  events: TEventSchemas;
136
137
  context?: TContextSchema;
137
- planner?: AgentPlanner<Agent<TContextSchema, TEventSchemas>>;
138
+ strategy?: AgentStrategy<Agent<TContextSchema, TEventSchemas>>;
138
139
  stringify?: typeof JSON.stringify;
139
140
  /**
140
141
  * A function that retrieves the agent's long term memory
@@ -147,15 +148,17 @@ export function createAgent<
147
148
  */
148
149
  logic?: AgentLogic<TEvents>;
149
150
  model: LanguageModel;
150
- } & GenerateTextOptions): Agent<TContextSchema, TEventSchemas> {
151
+ episodeId?: string;
152
+ }): Agent<TContextSchema, TEventSchemas> {
151
153
  return new Agent({
152
154
  id,
153
155
  context,
154
156
  events,
155
157
  description,
156
- planner,
158
+ strategy: strategy,
157
159
  model,
158
160
  logic,
161
+ episodeId,
159
162
  }) as any;
160
163
  }
161
164
 
@@ -177,11 +180,11 @@ export class Agent<
177
180
  public description?: string;
178
181
  public events: TEventSchemas;
179
182
  public context?: TContextSchema;
180
- public planner?: AgentPlanner<Agent<TContextSchema, TEventSchemas>>;
181
- public types: {
182
- events: TEvents;
183
- context: Compute<TContext>;
184
- };
183
+ public strategy: AgentStrategy<Agent<TContextSchema, TEventSchemas>>;
184
+ // public types: {
185
+ // events: TEvents;
186
+ // context: Compute<TContext>;
187
+ // };
185
188
  public model: LanguageModel;
186
189
  public memory: AgentLongTermMemory | undefined;
187
190
  public defaultOptions: AgentDecideOptions<AnyAgent> | undefined; // todo
@@ -194,7 +197,8 @@ export class Agent<
194
197
  model,
195
198
  events,
196
199
  context,
197
- planner = simplePlanner,
200
+ episodeId,
201
+ strategy = simpleStrategy,
198
202
  }: {
199
203
  logic: AgentLogic<TEvents>;
200
204
  id?: string;
@@ -203,17 +207,18 @@ export class Agent<
203
207
  model: GenerateTextOptions['model'];
204
208
  events: TEventSchemas;
205
209
  context?: TContextSchema;
206
- planner?: AgentPlanner<Agent<TContextSchema, TEventSchemas>>;
210
+ strategy?: AgentStrategy<Agent<TContextSchema, TEventSchemas>>;
211
+ episodeId?: string;
207
212
  }) {
208
213
  super(logic);
209
214
  this.model = model;
210
- this.episodeId = id ?? randomId();
215
+ this.episodeId = episodeId ?? randomId('episode-');
211
216
  this.name = name;
212
217
  this.description = description;
213
218
  this.events = events;
214
219
  this.context = context;
215
- this.planner = planner;
216
- this.types = {} as any;
220
+ this.strategy = strategy;
221
+ this.id = id ?? randomId();
217
222
 
218
223
  this.start();
219
224
  }
@@ -225,6 +230,13 @@ export class Agent<
225
230
  return this.on('message', (ev) => fn(ev.message));
226
231
  }
227
232
 
233
+ /**
234
+ * Called whenever the agent (LLM assistant) receives some feedback.
235
+ */
236
+ public onFeedback(fn: (feedback: AgentFeedback) => void) {
237
+ return this.on('feedback', (ev) => fn(ev.feedback));
238
+ }
239
+
228
240
  /**
229
241
  * Retrieves messages from the agent's short-term (local) memory.
230
242
  */
@@ -251,7 +263,6 @@ export class Agent<
251
263
  const feedback = {
252
264
  ...feedbackInput,
253
265
  attributes: { ...feedbackInput.attributes },
254
- reward: feedbackInput.reward ?? 0,
255
266
  timestamp: feedbackInput.timestamp ?? Date.now(),
256
267
  episodeId: this.episodeId,
257
268
  } satisfies AgentFeedback;
@@ -300,17 +311,17 @@ export class Agent<
300
311
  return this.getSnapshot().context.observations;
301
312
  }
302
313
 
303
- public addPlan(plan: AgentPlan<TEvents>) {
314
+ public addDecision(decision: AgentDecision<TEvents>) {
304
315
  this.send({
305
- type: 'agent.plan',
306
- plan,
316
+ type: 'agent.decision',
317
+ decision,
307
318
  });
308
319
  }
309
320
  /**
310
321
  * Retrieves strategies from the agent's short-term (local) memory.
311
322
  */
312
- public getPlans() {
313
- return this.getSnapshot().context.plans;
323
+ public getDecisions() {
324
+ return this.getSnapshot().context.decisions;
314
325
  }
315
326
 
316
327
  /**
@@ -361,13 +372,13 @@ export class Agent<
361
372
  actorRef: TActor,
362
373
  getInput: (
363
374
  observation: AgentObservation<TActor>
364
- ) => AgentDecisionInput | undefined
375
+ ) => AgentInteractInput<this> | void
365
376
  ): Subscription;
366
377
  public interact<TActor extends ActorRefLike>(
367
378
  actorRef: TActor,
368
379
  getInput?: (
369
380
  observation: AgentObservation<TActor>
370
- ) => AgentDecisionInput | undefined
381
+ ) => AgentInteractInput<this> | void
371
382
  ): Subscription {
372
383
  const actorRefCheck = isActorRef(actorRef) && actorRef.src;
373
384
  const machine = isMachineActor(actorRef) ? actorRef.src : undefined;
@@ -425,7 +436,7 @@ export class Agent<
425
436
  if ((actorRef as any)._processingStatus === 1) {
426
437
  handleObservation({
427
438
  prevState: undefined,
428
- event: { type: '' }, // TODO: unknown events?
439
+ event: undefined,
429
440
  state: actorRef.getSnapshot(),
430
441
  machine: (actorRef as any).src,
431
442
  });
@@ -478,14 +489,16 @@ export class Agent<
478
489
  }
479
490
 
480
491
  /**
481
- * Resolves with an `AgentPlan` based on the information provided in the `options`, including:
492
+ * Resolves with an `AgentDecision` based on the information provided in the `options`, including:
482
493
  *
483
494
  * - The `goal` for the agent to achieve
484
495
  * - The observed current `state`
485
496
  * - The `machine` (e.g. a state machine) that specifies what can happen next
486
497
  * - Additional `context`
487
498
  */
488
- public decide(opts: AgentDecideOptions<this>) {
499
+ public async decide(
500
+ opts: AgentDecideOptions<this>
501
+ ): Promise<AgentDecision<EventsFromAgent<this>> | undefined> {
489
502
  return agentDecide(this, opts);
490
503
  }
491
504
  }
@@ -154,7 +154,7 @@ test('interacts with an actor (late interaction)', async () => {
154
154
  expect(actor.getSnapshot().value).toBe('third');
155
155
  });
156
156
 
157
- test('agent.decide() makes a decision based on goal and state (simple planner)', async () => {
157
+ test('agent.decide() makes a decision based on goal and state (simple strategy)', async () => {
158
158
  const model = new MockLanguageModelV1({
159
159
  doGenerate,
160
160
  });
@@ -167,7 +167,7 @@ test('agent.decide() makes a decision based on goal and state (simple planner)',
167
167
  },
168
168
  });
169
169
 
170
- const plan = await agent.decide({
170
+ const decision = await agent.decide({
171
171
  goal: 'Make the best move',
172
172
  state: {
173
173
  value: 'playing',
@@ -188,8 +188,8 @@ test('agent.decide() makes a decision based on goal and state (simple planner)',
188
188
  }),
189
189
  });
190
190
 
191
- expect(plan).toBeDefined();
192
- expect(plan!.nextEvent).toEqual(
191
+ expect(decision).toBeDefined();
192
+ expect(decision!.nextEvent).toEqual(
193
193
  expect.objectContaining({
194
194
  type: 'MOVE',
195
195
  })
@@ -243,7 +243,7 @@ test.each([
243
243
  },
244
244
  });
245
245
 
246
- const plan = await agent.decide({
246
+ const decision = await agent.decide({
247
247
  goal: 'Make the best move',
248
248
  state: {
249
249
  value: 'playing',
@@ -263,10 +263,10 @@ test.each([
263
263
  });
264
264
 
265
265
  if (!succeed) {
266
- expect(plan).toBeUndefined();
266
+ expect(decision).toBeUndefined();
267
267
  } else {
268
- expect(plan).toBeDefined();
269
- expect(plan!.nextEvent).toEqual(
268
+ expect(decision).toBeDefined();
269
+ expect(decision!.nextEvent).toEqual(
270
270
  expect.objectContaining({
271
271
  type: 'MOVE',
272
272
  })
@@ -274,3 +274,51 @@ test.each([
274
274
  }
275
275
  }
276
276
  );
277
+
278
+ test.each([['MOVE'], ['FORFEIT']] as const)(
279
+ 'agent.decide() respects allowedEvents constraint (event: %s)',
280
+ async (allowedEventType) => {
281
+ const model = new MockLanguageModelV1({
282
+ doGenerate: async (params: LanguageModelV1CallOptions) => {
283
+ const keys =
284
+ params.mode.type === 'regular'
285
+ ? params.mode.tools?.map((t) => t.name)
286
+ : [];
287
+
288
+ return {
289
+ ...dummyResponseValues,
290
+ finishReason: 'tool-calls',
291
+ toolCalls: [
292
+ {
293
+ toolCallType: 'function',
294
+ toolCallId: 'call-1',
295
+ toolName: keys![0],
296
+ args: `{ "type": "${keys?.[0]}" }`,
297
+ },
298
+ ],
299
+ } as any;
300
+ },
301
+ });
302
+
303
+ const agent = createAgent({
304
+ id: 'test',
305
+ model,
306
+ events: {
307
+ MOVE: z.object({}),
308
+ SKIP: z.object({}),
309
+ FORFEIT: z.object({}),
310
+ },
311
+ });
312
+
313
+ const decision = await agent.decide({
314
+ goal: 'Make the best move',
315
+ state: {
316
+ value: 'playing',
317
+ context: {},
318
+ },
319
+ allowedEvents: [allowedEventType],
320
+ });
321
+
322
+ expect(decision?.nextEvent?.type).toEqual(allowedEventType);
323
+ }
324
+ );
package/src/decide.ts CHANGED
@@ -3,65 +3,72 @@ import {
3
3
  AnyAgent,
4
4
  AgentDecideOptions,
5
5
  AgentDecisionLogic,
6
- AgentDecisionInput,
7
- AgentPlanner,
8
- AgentPlan,
9
- EventsFromZodEventMapping,
10
- AgentPlanInput,
6
+ AgentDecision,
7
+ AgentDecideInput,
11
8
  TransitionData,
9
+ EventsFromAgent,
12
10
  } from './types';
13
- import { simplePlanner } from './planners/simple';
14
11
  import { getTransitions } from './utils';
15
12
  import { CoreMessage, CoreTool, tool } from 'ai';
16
13
 
17
14
  export async function agentDecide<T extends AnyAgent>(
18
15
  agent: T,
19
16
  options: AgentDecideOptions<T>
20
- ): Promise<AgentPlan<EventsFromZodEventMapping<T['events']>> | undefined> {
17
+ ): Promise<AgentDecision<EventsFromAgent<T>> | undefined> {
21
18
  const resolvedOptions = {
22
19
  ...agent.defaultOptions,
23
20
  ...options,
24
21
  };
25
22
  const {
26
- planner = simplePlanner as AgentPlanner<any>,
23
+ strategy = agent.strategy,
27
24
  goal,
25
+ allowedEvents,
28
26
  events = agent.events,
29
27
  state,
30
28
  machine,
31
29
  model = agent.model,
32
30
  messages,
33
- ...otherPlanInput
31
+ ...otherDecideInput
34
32
  } = resolvedOptions;
35
33
 
34
+ const filteredEventSchemas = allowedEvents
35
+ ? Object.fromEntries(
36
+ Object.entries(events).filter(([key]) => {
37
+ return allowedEvents.includes(key);
38
+ })
39
+ )
40
+ : events;
41
+
36
42
  let attempts = 0;
37
43
 
38
44
  const maxAttempts = resolvedOptions.maxAttempts ?? 2;
39
45
 
40
- let plan;
46
+ let decision: AgentDecision<any> | undefined;
41
47
 
42
48
  while (attempts++ < maxAttempts) {
43
- plan = await planner(agent, {
49
+ decision = await strategy(agent, {
44
50
  model,
45
51
  goal,
46
- events,
52
+ events: filteredEventSchemas,
47
53
  state,
48
54
  machine,
49
55
  messages: messages as CoreMessage[], // TODO: fix UIMessage thing
50
- ...otherPlanInput,
56
+ ...otherDecideInput,
51
57
  });
52
58
 
53
- if (plan?.nextEvent) {
54
- agent.addPlan(plan);
55
- await resolvedOptions.execute?.(plan.nextEvent);
59
+ if (decision?.nextEvent) {
60
+ agent.addDecision(decision);
61
+ await resolvedOptions.execute?.(decision.nextEvent);
62
+ break;
56
63
  }
57
64
  }
58
65
 
59
- return plan;
66
+ return decision;
60
67
  }
61
68
 
62
- export function fromDecision(
63
- agent: AnyAgent,
64
- defaultInput?: AgentDecisionInput
69
+ export function fromDecision<T extends AnyAgent>(
70
+ agent: T,
71
+ defaultInput?: AgentDecideInput<EventsFromAgent<T>>
65
72
  ): AgentDecisionLogic<any> {
66
73
  return fromPromise(async ({ input, self }) => {
67
74
  const parentRef = self._parent;
@@ -80,22 +87,25 @@ export function fromDecision(
80
87
  context: resolvedInput.context,
81
88
  };
82
89
 
83
- const plan = await agentDecide(agent, {
90
+ const decision = await agentDecide(agent, {
84
91
  machine: (parentRef as AnyActor).logic,
85
- state,
92
+ state: snapshot,
93
+ context: resolvedInput.context,
86
94
  execute: async (event) => {
87
95
  parentRef.send(event);
88
96
  },
89
97
  ...resolvedInput,
98
+ // @ts-ignore
99
+ messages: resolvedInput.messages,
90
100
  });
91
101
 
92
- return plan;
102
+ return decision;
93
103
  }) as AgentDecisionLogic<any>;
94
104
  }
95
105
 
96
106
  export function getToolMap<T extends AnyAgent>(
97
107
  _agent: T,
98
- input: AgentPlanInput<any>
108
+ input: AgentDecideInput<any>
99
109
  ): Record<string, CoreTool<any, any>> | undefined {
100
110
  // Get all of the possible next transitions
101
111
  const transitions: TransitionData[] = input.machine
@@ -0,0 +1,48 @@
1
+ import { generateText } from 'ai';
2
+ import {
3
+ AnyAgent,
4
+ AgentDecideInput,
5
+ AgentDecision,
6
+ PromptTemplate,
7
+ } from '../types';
8
+ import { getMessages } from '../text';
9
+ import { simpleStrategy } from './simple';
10
+ import { convertToXml } from '../utils';
11
+
12
+ const chainOfThoughtPromptTemplate: PromptTemplate<any> = ({
13
+ context,
14
+ goal,
15
+ }) => {
16
+ return `
17
+ ${convertToXml({ context, goal })}
18
+
19
+ How would you achieve the goal? Think step-by-step.
20
+ `.trim();
21
+ };
22
+
23
+ export async function chainOfThoughtStrategy<T extends AnyAgent>(
24
+ agent: T,
25
+ input: AgentDecideInput<any>
26
+ ): Promise<AgentDecision<any> | undefined> {
27
+ const prompt = chainOfThoughtPromptTemplate({
28
+ context: input.state.context,
29
+ goal: input.goal,
30
+ });
31
+
32
+ const messages = await getMessages(agent, prompt, input);
33
+
34
+ const model = input.model ? agent.wrap(input.model) : agent.model;
35
+
36
+ const result = await generateText({
37
+ model,
38
+ system: input.system ?? agent.description,
39
+ messages,
40
+ });
41
+
42
+ const decision = await simpleStrategy(agent, {
43
+ ...input,
44
+ messages: messages.concat(result.response.messages),
45
+ });
46
+
47
+ return decision;
48
+ }
@@ -1,7 +1,7 @@
1
- import { createAgent } from '../';
1
+ import { createAgent, TypesFromAgent } from '..';
2
2
  import { assign, createActor, setup } from 'xstate';
3
3
  import { z } from 'zod';
4
- import { experimental_createShortestPathPlanner } from './shortestPath';
4
+ import { experimental_shortestPathStrategy } from './shortestPath';
5
5
  import { test, expect } from 'vitest';
6
6
  import { dummyResponseValues, MockLanguageModelV1 } from '../mockModel';
7
7
 
@@ -35,10 +35,7 @@ test.skip('should find shortest path to goal', async () => {
35
35
  });
36
36
 
37
37
  const counterMachine = setup({
38
- types: {
39
- context: agent.types.context,
40
- events: agent.types.events,
41
- },
38
+ types: {} as TypesFromAgent<typeof agent>,
42
39
  }).createMachine({
43
40
  initial: 'counting',
44
41
  context: { count: 0 },
@@ -87,7 +84,7 @@ test.skip('should find shortest path to goal', async () => {
87
84
  }),
88
85
  goal: 'Get the counter to exactly 3',
89
86
  state: counterActor.getSnapshot(),
90
- planner: experimental_createShortestPathPlanner(),
87
+ strategy: experimental_shortestPathStrategy,
91
88
  });
92
89
 
93
90
  expect(decision?.nextEvent?.type).toBe('increment');