@statelyai/agent 0.0.8 → 0.1.1

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 (50) hide show
  1. package/.vscode/launch.json +12 -1
  2. package/CHANGELOG.md +18 -0
  3. package/dist/index.d.mts +3 -0
  4. package/dist/index.d.ts +286 -44
  5. package/dist/index.js +695 -1225
  6. package/dist/index.mjs +7 -0
  7. package/examples/chatbot.ts +79 -0
  8. package/examples/cot.ts +91 -0
  9. package/examples/email.ts +118 -0
  10. package/examples/example.ts +81 -0
  11. package/examples/goal.ts +94 -0
  12. package/examples/joke.ts +98 -84
  13. package/examples/multi.ts +103 -0
  14. package/examples/newspaper.ts +324 -0
  15. package/examples/number.ts +102 -0
  16. package/examples/raffle.ts +105 -0
  17. package/examples/simple.ts +39 -0
  18. package/examples/support.ts +147 -0
  19. package/examples/ticTacToe.ts +77 -77
  20. package/examples/todo.ts +135 -0
  21. package/examples/tutor.ts +100 -0
  22. package/examples/verify.ts +120 -0
  23. package/examples/weather.ts +42 -45
  24. package/examples/wiki.ts +30 -0
  25. package/examples/word.ts +168 -0
  26. package/package.json +29 -23
  27. package/readme.md +9 -38
  28. package/src/adapters/vercel.ts +7 -0
  29. package/src/agent-experimental.ts +221 -0
  30. package/src/agent.test.ts +187 -0
  31. package/src/agent.ts +260 -6
  32. package/src/decision.test.ts +179 -0
  33. package/src/decision.ts +83 -0
  34. package/src/index.ts +3 -2
  35. package/src/memory.ts +25 -0
  36. package/src/planners/shortestPathPlanner.ts +22 -0
  37. package/src/planners/simplePlanner.ts +126 -0
  38. package/src/schemas.ts +9 -20
  39. package/src/strategies/chain-of-note.ts +155 -0
  40. package/src/templates/defaultText.ts +18 -0
  41. package/src/templates/defaultToolCall.ts +10 -0
  42. package/src/text.ts +232 -0
  43. package/src/types.ts +363 -46
  44. package/src/utils.ts +13 -72
  45. package/tsconfig.json +1 -1
  46. package/examples/multiAgentCollaboration.ts +0 -0
  47. package/examples/numberGuesser.ts +0 -101
  48. package/examples/wordGuesser.ts +0 -144
  49. package/src/adapter.test.ts +0 -217
  50. package/src/adapters/openai.ts +0 -303
package/src/types.ts CHANGED
@@ -1,61 +1,378 @@
1
- import OpenAI from 'openai';
2
- import {
3
- ChatCompletionCreateParamsNonStreaming,
4
- ChatCompletionCreateParamsStreaming,
5
- } from 'openai/resources';
6
1
  import {
2
+ ActorLogic,
3
+ ActorRefFrom,
4
+ AnyActorRef,
7
5
  AnyEventObject,
8
- ObservableActorLogic,
6
+ AnyStateMachine,
7
+ EventFrom,
8
+ EventObject,
9
9
  PromiseActorLogic,
10
+ SnapshotFrom,
11
+ StateValue,
12
+ Subscription,
13
+ TransitionSnapshot,
14
+ Values,
10
15
  } from 'xstate';
16
+ import {
17
+ CoreMessage,
18
+ CoreTool,
19
+ generateText,
20
+ GenerateTextResult,
21
+ LanguageModel,
22
+ streamText,
23
+ StreamTextResult,
24
+ } from 'ai';
25
+ import { ZodEventMapping } from './schemas';
26
+ import { TypeOf } from 'zod';
27
+
28
+ export type GenerateTextOptions = Parameters<typeof generateText>[0];
29
+
30
+ export type StreamTextOptions = Parameters<typeof streamText>[0];
31
+
32
+ export type AgentPlanInput<TEvent extends EventObject> = {
33
+ model: LanguageModel;
34
+ state: ObservedState;
35
+ goal: string;
36
+ events: ZodEventMapping;
37
+ machine?: AnyStateMachine;
38
+ /**
39
+ * The previous plan
40
+ */
41
+ previousPlan?: AgentPlan<TEvent>;
42
+ };
43
+
44
+ export type AgentPlan<TEvent extends EventObject> = {
45
+ goal: string;
46
+ state: ObservedState;
47
+ content?: string;
48
+ steps?: Array<{
49
+ event: TEvent;
50
+ state?: ObservedState;
51
+ }>;
52
+ nextEvent: TEvent | undefined;
53
+ sessionId: string;
54
+ timestamp: number;
55
+ };
56
+
57
+ export interface TransitionData {
58
+ eventType: string;
59
+ description?: string;
60
+ guard?: { type: string };
61
+ target?: any;
62
+ }
11
63
 
12
- export interface StatelyAgentAdapter {
13
- model: string;
64
+ export type PromptTemplate<TEvents extends EventObject> = (data: {
65
+ goal: string;
14
66
  /**
15
- * Creates actor logic that chooses an event from all of the
16
- * possible next events of the parent state machine
17
- * and sends it to the parent actor.
67
+ * The observed state
18
68
  */
19
- fromEvent: <TInput>(
20
- inputFn: (input: TInput) => string | ChatCompletionCreateParamsNonStreaming
21
- ) => PromiseActorLogic<AnyEventObject[] | undefined, TInput>;
69
+ state?: ObservedState;
22
70
  /**
23
- * Creates actor logic that resolves with a chat completion.
71
+ * The context to provide.
72
+ * This overrides the observed state.context, if provided.
24
73
  */
25
- fromChat: <TInput>(
26
- inputFn: (input: TInput) => string | ChatCompletionCreateParamsNonStreaming
27
- ) => PromiseActorLogic<OpenAI.Chat.Completions.ChatCompletion, TInput>;
74
+ context?: any;
28
75
  /**
29
- * Creates actor logic that emits a chat completion stream.
76
+ * The state machine model of the observed environment
30
77
  */
31
- fromChatStream: <TInput>(
32
- inputFn: (input: TInput) => string | ChatCompletionCreateParamsStreaming
33
- ) => ObservableActorLogic<
34
- OpenAI.Chat.Completions.ChatCompletionChunk,
35
- TInput
36
- >;
78
+ machine?: unknown;
37
79
  /**
38
- * Creates actor logic that chooses a tool from the provided
39
- * tools and runs that tool.
80
+ * The potential next transitions that can be taken
81
+ * in the state machine
40
82
  */
41
- fromTool: <TInput>(
42
- inputFn: (input: TInput) => string | ChatCompletionCreateParamsNonStreaming,
43
- tools: {
44
- [key: string]: Tool<any, any>;
83
+ transitions?: TransitionData[];
84
+ /**
85
+ * Past observations
86
+ */
87
+ observations?: AgentObservation<any>[]; // TODO
88
+ feedback?: AgentFeedback[];
89
+ messages?: AgentMessageHistory[];
90
+ plans?: AgentPlan<TEvents>[];
91
+ }) => string;
92
+
93
+ export type AgentPlanner<T extends Agent<any>> = (
94
+ agent: T['eventTypes'],
95
+ options: AgentPlanInput<T['eventTypes']>
96
+ ) => Promise<AgentPlan<T['eventTypes']> | undefined>;
97
+
98
+ export type AgentDecideOptions = {
99
+ goal: string;
100
+ model?: LanguageModel;
101
+ context?: any;
102
+ state: ObservedState;
103
+ machine: AnyStateMachine;
104
+ execute?: (event: AnyEventObject) => Promise<void>;
105
+ planner?: AgentPlanner<any>;
106
+ events?: ZodEventMapping;
107
+ } & Omit<
108
+ Parameters<typeof generateText>[0],
109
+ 'model' | 'tools' | 'prompt' | 'messages'
110
+ >;
111
+
112
+ export interface AgentFeedback {
113
+ goal: string;
114
+ observationId: string;
115
+ attributes: Record<string, any>;
116
+ timestamp: number;
117
+ sessionId: string;
118
+ }
119
+
120
+ export interface AgentFeedbackInput {
121
+ goal: string;
122
+ observationId: string; // Observation ID;
123
+ attributes: Record<string, any>;
124
+ timestamp?: number;
125
+ }
126
+
127
+ export type AgentMessageHistory = CoreMessage & {
128
+ timestamp: number;
129
+ id: string;
130
+ /**
131
+ * The response ID of the message, which references
132
+ * which message this message is responding to, if any.
133
+ */
134
+ responseId?: string;
135
+ result?: GenerateTextResult<any>;
136
+ sessionId: string;
137
+ };
138
+
139
+ export type AgentMessageHistoryInput = CoreMessage & {
140
+ timestamp?: number;
141
+ id?: string;
142
+ /**
143
+ * The response ID of the message, which references
144
+ * which message this message is responding to, if any.
145
+ */
146
+ responseId?: string;
147
+ result?: GenerateTextResult<any>;
148
+ };
149
+
150
+ export interface AgentObservation<TActor extends AnyActorRef> {
151
+ id: string;
152
+ prevState: SnapshotFrom<TActor> | undefined;
153
+ event: EventFrom<TActor>;
154
+ state: SnapshotFrom<TActor>;
155
+ sessionId: string;
156
+ timestamp: number;
157
+ }
158
+
159
+ export interface AgentObservationInput {
160
+ id?: string;
161
+ prevState: ObservedState | undefined;
162
+ event: AnyEventObject;
163
+ state: ObservedState;
164
+ timestamp?: number;
165
+ }
166
+
167
+ export type AgentDecisionInput = {
168
+ goal: string;
169
+ model?: LanguageModel;
170
+ context?: any;
171
+ } & Omit<Parameters<typeof generateText>[0], 'model' | 'tools' | 'prompt'>;
172
+
173
+ export type AgentDecisionLogic<TEvents extends EventObject> = PromiseActorLogic<
174
+ AgentPlan<TEvents> | undefined,
175
+ AgentDecisionInput | string
176
+ >;
177
+
178
+ export type AgentEmitted<TEvents extends EventObject> =
179
+ | {
180
+ type: 'feedback';
181
+ feedback: AgentFeedback;
182
+ }
183
+ | {
184
+ type: 'observation';
185
+ observation: AgentObservation<any>; // TODO
186
+ }
187
+ | {
188
+ type: 'message';
189
+ message: AgentMessageHistory;
190
+ }
191
+ | {
192
+ type: 'plan';
193
+ plan: AgentPlan<TEvents>;
194
+ };
195
+
196
+ export type AgentLogic<TEvents extends EventObject> = ActorLogic<
197
+ TransitionSnapshot<AgentMemoryContext>,
198
+ | {
199
+ type: 'agent.feedback';
200
+ feedback: AgentFeedback;
45
201
  }
46
- ) => PromiseActorLogic<
47
- | {
48
- result: any;
49
- tool: string;
50
- toolCall: OpenAI.Chat.Completions.ChatCompletionMessageToolCall;
51
- }
52
- | undefined,
53
- TInput
54
- >;
55
- }
56
-
57
- export interface Tool<TInput, TOutput> {
58
- description: string;
59
- inputSchema: any;
60
- run: (input: TInput) => TOutput;
202
+ | {
203
+ type: 'agent.observe';
204
+ observation: AgentObservation<any>; // TODO
205
+ }
206
+ | {
207
+ type: 'agent.message';
208
+ message: AgentMessageHistory;
209
+ }
210
+ | {
211
+ type: 'agent.plan';
212
+ plan: AgentPlan<TEvents>;
213
+ },
214
+ any, // TODO: input
215
+ any,
216
+ AgentEmitted<TEvents>
217
+ >;
218
+
219
+ export type EventsFromZodEventMapping<TEventSchemas extends ZodEventMapping> =
220
+ Values<{
221
+ [K in keyof TEventSchemas & string]: {
222
+ type: K;
223
+ } & TypeOf<TEventSchemas[K]>;
224
+ }>;
225
+
226
+ export type Agent<TEvents extends EventObject> = ActorRefFrom<
227
+ AgentLogic<TEvents>
228
+ > & {
229
+ /**
230
+ * The general name of the agent. All agents with the same name are related and
231
+ * able to share experiences (observations, feedback) with each other.
232
+ */
233
+ name: string;
234
+ /**
235
+ * The unique id of the agent. This is used to partition message history.
236
+ */
237
+ id?: string;
238
+ description?: string;
239
+ events: ZodEventMapping;
240
+ eventTypes: TEvents;
241
+ model: LanguageModel;
242
+ defaultOptions: GenerateTextOptions;
243
+ memory: AgentLongTermMemory | undefined;
244
+ /**
245
+ * The adapter used to perform LLM actions such as
246
+ * `.generateText(…)` and `.streamText(…)`.
247
+ *
248
+ * Defaults to the Vercel AI SDK.
249
+ */
250
+ adapter: AIAdapter;
251
+
252
+ /**
253
+ * Resolves with an `AgentPlan` based on the information provided in the `options`, including:
254
+ *
255
+ * - The `goal` for the agent to achieve
256
+ * - The observed current `state`
257
+ * - The `logic` (e.g. a state machine) that specifies what can happen next
258
+ * - Additional `context`
259
+ */
260
+ decide: (
261
+ options: AgentDecideOptions
262
+ ) => Promise<AgentPlan<TEvents> | undefined>;
263
+
264
+ // Generate text
265
+ generateText: (
266
+ options: AgentGenerateTextOptions
267
+ ) => Promise<GenerateTextResult<Record<string, any>>>;
268
+
269
+ // Stream text
270
+ streamText: (
271
+ options: AgentStreamTextOptions
272
+ ) => Promise<StreamTextResult<Record<string, CoreTool<any, any>>>>;
273
+
274
+ addObservation: (observation: AgentObservationInput) => AgentObservation<any>; // TODO
275
+ addMessage: (history: AgentMessageHistoryInput) => AgentMessageHistory;
276
+ addFeedback: (feedbackItem: AgentFeedbackInput) => AgentFeedback;
277
+ addPlan: (plan: AgentPlan<TEvents>) => void;
278
+ /**
279
+ * Called whenever the agent (LLM assistant) receives or sends a message.
280
+ */
281
+ onMessage: (callback: (message: AgentMessageHistory) => void) => void;
282
+ /**
283
+ * Selects agent data from its context.
284
+ */
285
+ select: <T>(selector: (context: AgentMemoryContext) => T) => T;
286
+
287
+ /**
288
+ * Inspects state machine actor transitions and automatically observes
289
+ * (prevState, event, state) tuples.
290
+ */
291
+ interact: <TActor extends AnyActorRef>(
292
+ actorRef: TActor,
293
+ getInput?: (
294
+ observation: AgentObservation<TActor>
295
+ ) => AgentDecisionInput | undefined
296
+ ) => Subscription;
297
+ };
298
+
299
+ export type AnyAgent = Agent<any>;
300
+
301
+ export type FromAgent<T> = T | ((self: AnyAgent) => T | Promise<T>);
302
+
303
+ export interface CommonTextOptions {
304
+ prompt: FromAgent<string>;
305
+ model?: LanguageModel;
306
+ context?: Record<string, any>;
307
+ messages?: FromAgent<CoreMessage[]> | true;
308
+ template?: PromptTemplate<any>;
309
+ }
310
+
311
+ export type AgentGenerateTextOptions = Omit<
312
+ GenerateTextOptions,
313
+ 'model' | 'prompt' | 'messages'
314
+ > &
315
+ CommonTextOptions;
316
+
317
+ export type AgentStreamTextOptions = Omit<
318
+ StreamTextOptions,
319
+ 'model' | 'prompt' | 'messages'
320
+ > &
321
+ CommonTextOptions;
322
+
323
+ export interface ObservedState {
324
+ /**
325
+ * The current state value of the state machine, e.g.
326
+ * `"loading"` or `"processing"` or `"ready"`
327
+ */
328
+ value: StateValue;
329
+ /**
330
+ * Additional contextual data related to the current state
331
+ */
332
+ context: Record<string, unknown>;
333
+ }
334
+
335
+ export type ObservedStateFrom<TActor extends AnyActorRef> = Pick<
336
+ SnapshotFrom<TActor>,
337
+ 'value' | 'context'
338
+ >;
339
+
340
+ export type AgentMemoryContext = {
341
+ observations: AgentObservation<any>[]; // TODO
342
+ messages: AgentMessageHistory[];
343
+ plans: AgentPlan<any>[];
344
+ feedback: AgentFeedback[];
345
+ };
346
+
347
+ export type AgentMemory = AppendOnlyStorage<AgentMemoryContext>;
348
+
349
+ export interface AppendOnlyStorage<T extends Record<string, any[]>> {
350
+ append<K extends keyof T>(
351
+ sessionId: string,
352
+ key: K,
353
+ item: T[K][0]
354
+ ): Promise<void>;
355
+ getAll<K extends keyof T>(
356
+ sessionId: string,
357
+ key: K
358
+ ): Promise<T[K] | undefined>;
359
+ }
360
+
361
+ export interface AgentLongTermMemory {
362
+ get<K extends keyof AgentMemoryContext>(
363
+ key: K
364
+ ): Promise<AgentMemoryContext[K]>;
365
+ append<K extends keyof AgentMemoryContext>(
366
+ key: K,
367
+ item: AgentMemoryContext[K][0]
368
+ ): Promise<void>;
369
+ set<K extends keyof AgentMemoryContext>(
370
+ key: K,
371
+ items: AgentMemoryContext[K]
372
+ ): Promise<void>;
373
+ }
374
+
375
+ export interface AIAdapter {
376
+ generateText: typeof generateText;
377
+ streamText: typeof streamText;
61
378
  }
package/src/utils.ts CHANGED
@@ -1,81 +1,22 @@
1
- import { AnyMachineSnapshot, AnyStateNode, Prop, Values } from 'xstate';
2
- import { FromSchema } from 'json-schema-to-ts';
3
- import { JSONSchema7 } from 'json-schema-to-ts/lib/types/definitions';
4
- import zodToJsonSchema, { JsonSchema7Type } from 'zod-to-json-schema';
5
- import { ZodEventTypes } from './schemas';
6
- import { z } from 'zod';
1
+ import { AnyMachineSnapshot, AnyStateNode } from 'xstate';
2
+ import { TransitionData } from './types';
7
3
 
8
- export function getAllTransitions(state: AnyMachineSnapshot) {
4
+ export function getAllTransitions(state: AnyMachineSnapshot): TransitionData[] {
9
5
  const nodes = state._nodes;
10
6
  const transitions = (nodes as AnyStateNode[])
11
7
  .map((node) => [...(node as AnyStateNode).transitions.values()])
12
- .flat(2);
8
+ .flat(2)
9
+ .map((transition) => ({
10
+ ...transition,
11
+ guard:
12
+ typeof transition.guard === 'string'
13
+ ? { type: transition.guard }
14
+ : (transition.guard as any), // TODO: fix
15
+ }));
13
16
 
14
17
  return transitions;
15
18
  }
16
19
 
17
- export type EventSchemas = {
18
- [key: string]: {
19
- description?: string;
20
- properties?: {
21
- [key: string]: JsonSchema7Type;
22
- };
23
- };
24
- };
25
-
26
- export type ContextSchema = JSONSchema7 & { type: 'object' };
27
-
28
- export type ConvertToJSONSchemas<T> = {
29
- [K in keyof T]: {
30
- properties: { type: { const: K } } & Prop<T[K], 'properties'>;
31
- type: 'object';
32
- required: Array<(keyof Prop<T[K], 'properties'> & string) | 'type'>;
33
- additionalProperties: false;
34
- };
35
- } & {};
36
-
37
- export function createEventSchemas<T extends EventSchemas>(
38
- eventSchemaMap: T
39
- ): ConvertToJSONSchemas<T> {
40
- const resolvedEventSchemaMap = {};
41
-
42
- for (const [key, schema] of Object.entries(eventSchemaMap)) {
43
- // @ts-ignore
44
- resolvedEventSchemaMap[key] = {
45
- type: 'object',
46
- required: ['type'],
47
- properties: {
48
- type: {
49
- const: key,
50
- },
51
- ...schema.properties,
52
- },
53
- additionalProperties: false,
54
- ...schema,
55
- } as JSONSchema7;
56
- }
57
-
58
- return resolvedEventSchemaMap as ConvertToJSONSchemas<T>;
20
+ export function wrapInXml(tagName: string, content: string): string {
21
+ return `<${tagName}>${content}</${tagName}>`;
59
22
  }
60
-
61
- export function createZodEventSchemas<T extends ZodEventTypes>(
62
- eventSchemaMap: T
63
- ): {
64
- [K in keyof T]: unknown;
65
- } {
66
- const resolvedEventSchemaMap = {};
67
-
68
- for (const [eventType, zodType] of Object.entries(eventSchemaMap)) {
69
- // @ts-ignore
70
- resolvedEventSchemaMap[eventType] = zodToJsonSchema(
71
- zodType.extend({
72
- type: z.literal(eventType),
73
- })
74
- );
75
- }
76
-
77
- return resolvedEventSchemaMap as ConvertToJSONSchemas<T>;
78
- }
79
-
80
- export type InferEventsFromSchemas<T extends ConvertToJSONSchemas<any>> =
81
- FromSchema<Values<T>>;
package/tsconfig.json CHANGED
@@ -52,7 +52,7 @@
52
52
  // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
53
53
  // "declarationMap": true, /* Create sourcemaps for d.ts files. */
54
54
  // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
55
- // "sourceMap": true, /* Create source map files for emitted JavaScript files. */
55
+ "sourceMap": true /* Create source map files for emitted JavaScript files. */,
56
56
  // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
57
57
  // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
58
58
  // "outDir": "./", /* Specify an output folder for all emitted files. */
File without changes
@@ -1,101 +0,0 @@
1
- import OpenAI from 'openai';
2
- import { createAgent, createOpenAIAdapter, defineEvents } from '../src';
3
- import { assign, setup } from 'xstate';
4
- import { z } from 'zod';
5
- const openai = new OpenAI({
6
- apiKey: process.env.OPENAI_API_KEY,
7
- });
8
-
9
- const adapter = createOpenAIAdapter(openai, {
10
- model: 'gpt-3.5-turbo-1106',
11
- });
12
-
13
- const guessLogic = adapter.fromEvent(
14
- ({
15
- previousGuesses,
16
- lastResult,
17
- }: {
18
- previousGuesses: number[];
19
- lastResult: string;
20
- }) => `
21
- Guess the number between 1 and 10. The previous guesses were ${
22
- previousGuesses.length ? previousGuesses.join(', ') : 'not made yet'
23
- } and the last result was ${lastResult}.
24
- `
25
- );
26
-
27
- const events = defineEvents({
28
- guess: z.object({
29
- number: z.number().min(1).max(10).describe('The number guessed'),
30
- }),
31
- });
32
-
33
- const machine = setup({
34
- types: {
35
- context: {} as {
36
- previousGuesses: number[];
37
- answer: number;
38
- },
39
- input: {} as { answer: number },
40
- events: events.types,
41
- },
42
- schemas: {
43
- events: events.schemas,
44
- },
45
- actors: {
46
- guessLogic,
47
- },
48
- }).createMachine({
49
- context: ({ input }) => ({
50
- answer: input.answer,
51
- previousGuesses: [],
52
- }),
53
- initial: 'guessing',
54
- states: {
55
- guessing: {
56
- always: {
57
- guard: ({ context }) =>
58
- context.answer === context.previousGuesses.at(-1),
59
- target: 'winner',
60
- },
61
- invoke: {
62
- src: 'guessLogic',
63
- input: ({ context }) => ({
64
- previousGuesses: context.previousGuesses,
65
- lastResult:
66
- context.previousGuesses.length === 0
67
- ? 'not given yet'
68
- : context.previousGuesses.at(-1)! - context.answer > 0
69
- ? 'too high'
70
- : 'too low',
71
- }),
72
- },
73
- on: {
74
- guess: {
75
- actions: assign({
76
- previousGuesses: ({ context, event }) => [
77
- ...context.previousGuesses,
78
- event.number,
79
- ],
80
- }),
81
- target: 'guessing',
82
- reenter: true,
83
- },
84
- },
85
- },
86
- winner: {
87
- type: 'final',
88
- },
89
- },
90
- });
91
-
92
- const agent = createAgent(machine, {
93
- input: { answer: 4 },
94
- inspect: (ev) => {
95
- if (ev.type === '@xstate.event') {
96
- console.log(ev.event);
97
- }
98
- },
99
- });
100
-
101
- agent.start();