@statelyai/agent 1.1.6 → 2.0.0-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/.changeset/light-hats-drive.md +9 -0
  2. package/.changeset/pre.json +10 -0
  3. package/.vscode/launch.json +6 -0
  4. package/CHANGELOG.md +10 -0
  5. package/dist/index.d.mts +262 -165
  6. package/dist/index.d.ts +262 -165
  7. package/dist/index.js +368 -263
  8. package/dist/index.mjs +371 -261
  9. package/examples/chatbot-alt.ts +57 -0
  10. package/examples/chatbot.ts +11 -16
  11. package/examples/cot.ts +25 -22
  12. package/examples/customer-service-sim.ts +107 -0
  13. package/examples/email.ts +14 -14
  14. package/examples/example.ts +5 -5
  15. package/examples/executor.ts +66 -0
  16. package/examples/goal.ts +11 -11
  17. package/examples/helpers/helpers.ts +26 -14
  18. package/examples/joke.ts +78 -75
  19. package/examples/jugs.ts +125 -0
  20. package/examples/multi.ts +4 -4
  21. package/examples/newspaper.ts +98 -104
  22. package/examples/number.ts +5 -4
  23. package/examples/raffle.ts +10 -11
  24. package/examples/river-crossing.ts +140 -0
  25. package/examples/sandbox.ts +1 -1
  26. package/examples/simple.ts +4 -2
  27. package/examples/summary.ts +121 -0
  28. package/examples/support.ts +5 -5
  29. package/examples/ticTacToe.ts +86 -45
  30. package/examples/todo.ts +6 -6
  31. package/examples/tutor.ts +13 -13
  32. package/examples/verify.ts +2 -2
  33. package/examples/weather.ts +5 -8
  34. package/examples/wiki.ts +26 -7
  35. package/examples/word.ts +15 -10
  36. package/package.json +13 -10
  37. package/readme.md +1 -1
  38. package/src/agent-experimental.ts +1 -1
  39. package/src/agent.test.ts +117 -228
  40. package/src/agent.ts +469 -81
  41. package/src/{decision.test.ts → decide.test.ts} +26 -50
  42. package/src/decide.ts +153 -0
  43. package/src/index.ts +1 -1
  44. package/src/middleware.ts +103 -0
  45. package/src/mockModel.ts +47 -0
  46. package/src/planners/shortestPathPlanner.ts +151 -13
  47. package/src/planners/simplePlanner.ts +57 -85
  48. package/src/strategies/chain-of-note.ts +6 -55
  49. package/src/text.ts +51 -144
  50. package/src/types.ts +172 -204
  51. package/src/utils.ts +37 -4
  52. package/src/adapters/vercel.ts +0 -7
  53. package/src/decision.ts +0 -84
  54. package/src/memory.ts +0 -25
package/dist/index.js CHANGED
@@ -38,10 +38,10 @@ __export(src_exports, {
38
38
  module.exports = __toCommonJS(src_exports);
39
39
 
40
40
  // src/agent.ts
41
- var import_xstate3 = require("xstate");
41
+ var import_xstate4 = require("xstate");
42
42
 
43
43
  // src/planners/simplePlanner.ts
44
- var import_ai = require("ai");
44
+ var import_ai3 = require("ai");
45
45
 
46
46
  // src/utils.ts
47
47
  var import_object_hash = __toESM(require("object-hash"));
@@ -79,10 +79,10 @@ function getAllMachineTransitions(stateNode) {
79
79
  function wrapInXml(tagName, content) {
80
80
  return `<${tagName}>${content}</${tagName}>`;
81
81
  }
82
- function randomId() {
82
+ function randomId(prefix) {
83
83
  const timestamp = Date.now().toString(36);
84
84
  const random = Math.random().toString(36).substring(2, 9);
85
- return timestamp + random;
85
+ return `${prefix || ""}${timestamp}${random}`;
86
86
  }
87
87
  var machineHashes = /* @__PURE__ */ new WeakMap();
88
88
  function getMachineHash(machine) {
@@ -92,6 +92,23 @@ function getMachineHash(machine) {
92
92
  machineHashes.set(machine, machineHash);
93
93
  return machineHash;
94
94
  }
95
+ function isActorRef(actorRefLike) {
96
+ return "src" in actorRefLike && "system" in actorRefLike && "sessionId" in actorRefLike;
97
+ }
98
+ function getTransitions(state, machine) {
99
+ if (!machine) {
100
+ return [];
101
+ }
102
+ const resolvedState = machine.resolveState({
103
+ ...state,
104
+ // Need this property defined to make TS happy
105
+ context: state.context
106
+ });
107
+ return getAllTransitions(resolvedState);
108
+ }
109
+
110
+ // src/planners/simplePlanner.ts
111
+ var import_xstate3 = require("xstate");
95
112
 
96
113
  // src/templates/defaultText.ts
97
114
  var defaultTextTemplate = (data) => {
@@ -106,6 +123,7 @@ ${data.goal}
106
123
  };
107
124
 
108
125
  // src/text.ts
126
+ var import_ai = require("ai");
109
127
  var import_xstate = require("xstate");
110
128
  async function getMessages(agent, prompt, options) {
111
129
  let messages = [];
@@ -120,120 +138,26 @@ async function getMessages(agent, prompt, options) {
120
138
  });
121
139
  return messages;
122
140
  }
123
- async function agentGenerateText(agent, options) {
124
- const resolvedOptions = {
125
- ...agent.defaultOptions,
126
- ...options,
127
- correlationId: options.correlationId ?? randomId()
128
- };
129
- const template = resolvedOptions.template ?? defaultTextTemplate;
130
- const id = randomId();
131
- const goal = typeof resolvedOptions.prompt === "string" ? resolvedOptions.prompt : await resolvedOptions.prompt(agent);
132
- const promptWithContext = template({
133
- goal,
134
- context: resolvedOptions.context
135
- });
136
- const messages = await getMessages(agent, promptWithContext, resolvedOptions);
137
- agent.addMessage({
138
- id,
139
- role: "user",
140
- content: promptWithContext,
141
- timestamp: Date.now(),
142
- correlationId: resolvedOptions.correlationId,
143
- parentCorrelationId: resolvedOptions.parentCorrelationId
144
- });
145
- const result = await agent.adapter.generateText({
146
- ...resolvedOptions,
147
- prompt: void 0,
148
- messages
149
- });
150
- agent.addMessage({
151
- content: result.text,
152
- id,
153
- role: "assistant",
154
- timestamp: Date.now(),
155
- responseId: id,
156
- result,
157
- correlationId: resolvedOptions.correlationId,
158
- parentCorrelationId: resolvedOptions.parentCorrelationId
159
- });
160
- return {
161
- ...result,
162
- parentCorrelationId: resolvedOptions.parentCorrelationId,
163
- correlationId: resolvedOptions.correlationId
164
- };
165
- }
166
- async function agentStreamText(agent, options) {
167
- const resolvedOptions = {
168
- ...agent.defaultOptions,
169
- ...options,
170
- correlationId: options.correlationId ?? randomId()
171
- };
172
- const template = resolvedOptions.template ?? defaultTextTemplate;
173
- const id = randomId();
174
- const goal = typeof resolvedOptions.prompt === "string" ? resolvedOptions.prompt : await resolvedOptions.prompt(agent);
175
- const promptWithContext = template({
176
- goal,
177
- context: resolvedOptions.context
178
- });
179
- const messages = await getMessages(agent, promptWithContext, resolvedOptions);
180
- agent.addMessage({
181
- role: "user",
182
- content: promptWithContext,
183
- id,
184
- timestamp: Date.now(),
185
- correlationId: resolvedOptions.correlationId,
186
- parentCorrelationId: resolvedOptions.parentCorrelationId
187
- });
188
- const result = await agent.adapter.streamText({
189
- ...resolvedOptions,
190
- prompt: void 0,
191
- messages,
192
- onFinish: async (res) => {
193
- agent.addMessage({
194
- role: "assistant",
195
- result: {
196
- text: res.text,
197
- finishReason: res.finishReason,
198
- logprobs: void 0,
199
- responseMessages: [],
200
- toolCalls: [],
201
- toolResults: [],
202
- usage: res.usage,
203
- warnings: res.warnings,
204
- rawResponse: res.rawResponse,
205
- roundtrips: [],
206
- // TODO: how do we get this information?,
207
- steps: res.steps,
208
- response: res.response,
209
- experimental_providerMetadata: res.experimental_providerMetadata
210
- },
211
- content: res.text,
212
- id: randomId(),
213
- timestamp: Date.now(),
214
- responseId: id,
215
- correlationId: resolvedOptions.correlationId,
216
- parentCorrelationId: resolvedOptions.parentCorrelationId
217
- });
218
- }
219
- });
220
- return {
221
- ...result,
222
- textStream: result.textStream,
223
- fullStream: result.fullStream,
224
- parentCorrelationId: resolvedOptions.parentCorrelationId,
225
- correlationId: resolvedOptions.correlationId
226
- };
227
- }
228
- function fromTextStream(agent, defaultOptions) {
141
+ function fromTextStream(agent, options) {
142
+ const template = options?.template ?? defaultTextTemplate;
229
143
  return (0, import_xstate.fromObservable)(({ input }) => {
230
144
  const observers = /* @__PURE__ */ new Set();
231
145
  (async () => {
232
- const result = await agentStreamText(agent, {
233
- ...defaultOptions,
234
- ...input,
146
+ const model = input.model ? agent.wrap(input.model) : agent.model;
147
+ const goal = typeof input.prompt === "string" ? input.prompt : await input.prompt(agent);
148
+ const promptWithContext = template({
149
+ goal,
235
150
  context: input.context
236
151
  });
152
+ const messages = await getMessages(agent, promptWithContext, input);
153
+ const result = await (0, import_ai.streamText)({
154
+ ...options,
155
+ ...input,
156
+ prompt: void 0,
157
+ // overwritten by messages
158
+ model,
159
+ messages
160
+ });
237
161
  for await (const part of result.fullStream) {
238
162
  if (part.type === "text-delta") {
239
163
  observers.forEach((observer) => {
@@ -255,32 +179,89 @@ function fromTextStream(agent, defaultOptions) {
255
179
  };
256
180
  });
257
181
  }
258
- function fromText(agent, defaultOptions) {
182
+ function fromText(agent, options) {
183
+ const resolvedOptions = {
184
+ ...agent.defaultOptions,
185
+ ...options
186
+ };
187
+ const template = resolvedOptions.template ?? defaultTextTemplate;
259
188
  return (0, import_xstate.fromPromise)(async ({ input }) => {
260
- return await agentGenerateText(agent, {
261
- ...input,
262
- ...defaultOptions,
189
+ const goal = typeof input.prompt === "string" ? input.prompt : await input.prompt(agent);
190
+ const promptWithContext = template({
191
+ goal,
263
192
  context: input.context
264
193
  });
194
+ const messages = await getMessages(agent, promptWithContext, input);
195
+ const model = input.model ? agent.wrap(input.model) : agent.model;
196
+ return await (0, import_ai.generateText)({
197
+ ...input,
198
+ ...options,
199
+ prompt: void 0,
200
+ messages,
201
+ model
202
+ });
265
203
  });
266
204
  }
267
205
 
268
- // src/planners/simplePlanner.ts
269
- function getTransitions(state, machine) {
270
- if (!machine) {
271
- return [];
206
+ // src/decide.ts
207
+ var import_xstate2 = require("xstate");
208
+ var import_ai2 = require("ai");
209
+ async function agentDecide(agent, options) {
210
+ const resolvedOptions = {
211
+ ...agent.defaultOptions,
212
+ ...options
213
+ };
214
+ const {
215
+ planner = simplePlanner,
216
+ goal,
217
+ events = agent.events,
218
+ state,
219
+ machine,
220
+ model = agent.model,
221
+ ...otherPlanInput
222
+ } = resolvedOptions;
223
+ const plan = await planner(agent, {
224
+ model,
225
+ goal,
226
+ events,
227
+ state,
228
+ machine,
229
+ ...otherPlanInput
230
+ });
231
+ if (plan?.nextEvent) {
232
+ agent.addPlan(plan);
233
+ await resolvedOptions.execute?.(plan.nextEvent);
272
234
  }
273
- const resolvedState = machine.resolveState(state);
274
- return getAllTransitions(resolvedState);
235
+ return plan;
275
236
  }
276
- var simplePlannerPromptTemplate = (data) => {
277
- return `
278
- ${defaultTextTemplate(data)}
279
-
280
- Make at most one tool call to achieve the above goal. If the goal cannot be achieved with any tool calls, do not make any tool call.
281
- `.trim();
282
- };
283
- async function simplePlanner(agent, input) {
237
+ function fromDecision(agent, defaultInput) {
238
+ return (0, import_xstate2.fromPromise)(async ({ input, self }) => {
239
+ const parentRef = self._parent;
240
+ if (!parentRef) {
241
+ return;
242
+ }
243
+ const snapshot = parentRef.getSnapshot();
244
+ const inputObject = typeof input === "string" ? { goal: input } : input;
245
+ const resolvedInput = {
246
+ ...defaultInput,
247
+ ...inputObject
248
+ };
249
+ const state = {
250
+ value: snapshot.value,
251
+ context: resolvedInput.context
252
+ };
253
+ const plan = await agentDecide(agent, {
254
+ machine: parentRef.logic,
255
+ state,
256
+ execute: async (event) => {
257
+ parentRef.send(event);
258
+ },
259
+ ...resolvedInput
260
+ });
261
+ return plan;
262
+ });
263
+ }
264
+ function getToolMap(_agent, input) {
284
265
  const transitions = input.machine ? getTransitions(input.state, input.machine) : Object.entries(input.events).map(([eventType, { description }]) => ({
285
266
  eventType,
286
267
  description
@@ -305,7 +286,7 @@ async function simplePlanner(agent, input) {
305
286
  if (!toolZodType) {
306
287
  continue;
307
288
  }
308
- toolMap[toolTransitionData.name] = (0, import_ai.tool)({
289
+ toolMap[toolTransitionData.name] = (0, import_ai2.tool)({
309
290
  description: toolZodType?.description ?? toolTransitionData.description,
310
291
  parameters: toolZodType,
311
292
  execute: async (params) => {
@@ -320,17 +301,55 @@ async function simplePlanner(agent, input) {
320
301
  if (!Object.keys(toolMap).length) {
321
302
  return void 0;
322
303
  }
304
+ return toolMap;
305
+ }
306
+
307
+ // src/planners/simplePlanner.ts
308
+ var simplePlannerPromptTemplate = (data) => {
309
+ return `
310
+ ${defaultTextTemplate(data)}
311
+
312
+ Make at most one tool call to achieve the above goal. If the goal cannot be achieved with any tool calls, do not make any tool call.
313
+ `.trim();
314
+ };
315
+ async function simplePlanner(agent, input) {
316
+ const toolMap = getToolMap(agent, input);
317
+ if (!toolMap) {
318
+ return void 0;
319
+ }
323
320
  const prompt = simplePlannerPromptTemplate({
324
321
  context: input.state.context,
325
322
  goal: input.goal
326
323
  });
327
324
  const messages = await getMessages(agent, prompt, input);
328
- const result = await agent.generateText({
329
- toolChoice: "required",
330
- ...input,
331
- prompt,
325
+ const model = input.model ? agent.wrap(input.model) : agent.model;
326
+ const {
327
+ state,
328
+ machine,
329
+ previousPlan,
330
+ events,
331
+ goal,
332
+ model: _,
333
+ ...rest
334
+ } = input;
335
+ const machineState = input.machine ? input.machine.resolveState({
336
+ ...input.state,
337
+ context: input.state.context
338
+ }) : void 0;
339
+ const result = await (0, import_ai3.generateText)({
340
+ ...rest,
341
+ model,
332
342
  messages,
333
- tools: toolMap
343
+ tools: toolMap,
344
+ toolChoice: input.toolChoice ?? "required"
345
+ });
346
+ result.responseMessages.forEach((m) => {
347
+ const message = m;
348
+ agent.addMessage({
349
+ ...message,
350
+ id: randomId(),
351
+ timestamp: Date.now()
352
+ });
334
353
  });
335
354
  const singleResult = result.toolResults[0];
336
355
  if (!singleResult) {
@@ -338,91 +357,100 @@ async function simplePlanner(agent, input) {
338
357
  return void 0;
339
358
  }
340
359
  return {
360
+ planner: "simple",
341
361
  goal: input.goal,
342
- state: input.state,
343
- execute: async (state) => {
344
- if (JSON.stringify(state) === JSON.stringify(input.state)) {
345
- return singleResult.result;
346
- }
347
- return void 0;
348
- },
362
+ goalState: input.state,
349
363
  nextEvent: singleResult.result,
350
- sessionId: agent.sessionId,
351
- timestamp: Date.now()
364
+ episodeId: agent.episodeId,
365
+ timestamp: Date.now(),
366
+ paths: [
367
+ {
368
+ state: void 0,
369
+ steps: [
370
+ {
371
+ event: singleResult.result,
372
+ state: machine && machineState ? (0, import_xstate3.getNextSnapshot)(machine, machineState, singleResult.result) : void 0
373
+ }
374
+ ]
375
+ }
376
+ ]
352
377
  };
353
378
  }
354
379
 
355
- // src/decision.ts
356
- var import_xstate2 = require("xstate");
357
- async function agentDecide(agent, options) {
358
- const resolvedOptions = {
359
- ...agent.defaultOptions,
360
- ...options
361
- };
362
- const {
363
- planner = simplePlanner,
364
- goal,
365
- events = agent.events,
366
- state,
367
- machine,
368
- model = agent.model,
369
- ...otherPlanInput
370
- } = resolvedOptions;
371
- const plan = await planner(agent, {
372
- model,
373
- goal,
374
- events,
375
- state,
376
- machine,
377
- ...otherPlanInput
378
- });
379
- if (plan?.nextEvent) {
380
- agent.addPlan(plan);
381
- await resolvedOptions.execute?.(plan.nextEvent);
382
- }
383
- return plan;
384
- }
385
- function fromDecision(agent, defaultInput) {
386
- return (0, import_xstate2.fromPromise)(async ({ input, self }) => {
387
- const parentRef = self._parent;
388
- if (!parentRef) {
389
- return;
380
+ // src/agent.ts
381
+ var import_ai4 = require("ai");
382
+
383
+ // src/middleware.ts
384
+ function createAgentMiddleware(agent) {
385
+ const middleware = {
386
+ transformParams: async ({ params }) => {
387
+ return params;
388
+ },
389
+ wrapGenerate: async ({ doGenerate, params }) => {
390
+ const id = randomId();
391
+ params.prompt.forEach((p) => {
392
+ agent.addMessage({
393
+ id,
394
+ ...p,
395
+ timestamp: Date.now(),
396
+ correlationId: params.providerMetadata?.correlationId,
397
+ parentCorrelationId: params.providerMetadata?.parentCorrelationId
398
+ });
399
+ });
400
+ const result = await doGenerate();
401
+ return result;
402
+ },
403
+ wrapStream: async ({ doStream, params }) => {
404
+ const id = randomId();
405
+ params.prompt.forEach((message) => {
406
+ message.content;
407
+ agent.addMessage({
408
+ id,
409
+ ...message,
410
+ timestamp: Date.now(),
411
+ correlationId: params.providerMetadata?.correlationId,
412
+ parentCorrelationId: params.providerMetadata?.parentCorrelationId
413
+ });
414
+ });
415
+ const { stream, ...rest } = await doStream();
416
+ let generatedText = "";
417
+ const transformStream = new TransformStream({
418
+ transform(chunk, controller) {
419
+ if (chunk.type === "text-delta") {
420
+ generatedText += chunk.textDelta;
421
+ }
422
+ controller.enqueue(chunk);
423
+ },
424
+ flush() {
425
+ const content = [];
426
+ if (generatedText) {
427
+ content.push({
428
+ type: "text",
429
+ text: generatedText
430
+ });
431
+ }
432
+ agent.addMessage({
433
+ id: randomId(),
434
+ timestamp: Date.now(),
435
+ role: "assistant",
436
+ content,
437
+ responseId: id,
438
+ correlationId: params.providerMetadata?.correlationId,
439
+ parentCorrelationId: params.providerMetadata?.parentCorrelationId
440
+ });
441
+ }
442
+ });
443
+ return {
444
+ stream: stream.pipeThrough(transformStream),
445
+ ...rest
446
+ };
390
447
  }
391
- const snapshot = parentRef.getSnapshot();
392
- const inputObject = typeof input === "string" ? { goal: input } : input;
393
- const resolvedInput = {
394
- ...defaultInput,
395
- ...inputObject
396
- };
397
- const contextToInclude = resolvedInput.context === true ? (
398
- // include entire context
399
- parentRef.getSnapshot().context
400
- ) : resolvedInput.context;
401
- const state = {
402
- value: snapshot.value,
403
- context: contextToInclude
404
- };
405
- const plan = await agentDecide(agent, {
406
- machine: parentRef.logic,
407
- state,
408
- execute: async (event) => {
409
- parentRef.send(event);
410
- },
411
- ...resolvedInput
412
- });
413
- return plan;
414
- });
448
+ };
449
+ return middleware;
415
450
  }
416
451
 
417
- // src/adapters/vercel.ts
418
- var import_ai2 = require("ai");
419
- var vercelAdapter = {
420
- generateText: import_ai2.generateText,
421
- streamText: import_ai2.streamText
422
- };
423
-
424
452
  // src/agent.ts
425
- var agentLogic = (0, import_xstate3.fromTransition)(
453
+ var agentLogic = (0, import_xstate4.fromTransition)(
426
454
  (state, event, { emit }) => {
427
455
  switch (event.type) {
428
456
  case "agent.feedback": {
@@ -474,6 +502,7 @@ var agentLogic = (0, import_xstate3.fromTransition)(
474
502
  })
475
503
  );
476
504
  function createAgent({
505
+ id,
477
506
  name,
478
507
  description,
479
508
  model,
@@ -483,92 +512,133 @@ function createAgent({
483
512
  stringify = JSON.stringify,
484
513
  getMemory,
485
514
  logic = agentLogic,
486
- adapter = vercelAdapter,
487
515
  ...generateTextOptions
488
516
  }) {
489
- const agent = (0, import_xstate3.createActor)(logic);
490
- agent.events = events;
491
- agent.model = model;
492
- agent.name = name;
493
- agent.description = description;
494
- agent.adapter = adapter;
495
- agent.defaultOptions = { ...generateTextOptions, model };
496
- agent.select = (selector) => {
497
- return selector(agent.getSnapshot().context);
498
- };
499
- agent.memory = getMemory ? getMemory(agent) : void 0;
500
- agent.onMessage = (callback) => {
501
- agent.on("message", (ev) => callback(ev.message));
502
- };
503
- agent.decide = (opts) => {
504
- return agentDecide(agent, opts);
505
- };
506
- agent.addMessage = (messageInput) => {
517
+ return new Agent({
518
+ id,
519
+ context,
520
+ events,
521
+ name,
522
+ description,
523
+ planner,
524
+ model,
525
+ logic
526
+ });
527
+ }
528
+ var Agent = class extends import_xstate4.Actor {
529
+ // todo
530
+ constructor({
531
+ logic = agentLogic,
532
+ id,
533
+ name,
534
+ description,
535
+ model,
536
+ events,
537
+ context,
538
+ planner = simplePlanner
539
+ }) {
540
+ super(logic);
541
+ this.model = model;
542
+ this.episodeId = id ?? randomId();
543
+ this.name = name;
544
+ this.description = description;
545
+ this.events = events;
546
+ this.context = context;
547
+ this.planner = planner;
548
+ this.types = {};
549
+ this.start();
550
+ }
551
+ /**
552
+ * Called whenever the agent (LLM assistant) receives or sends a message.
553
+ */
554
+ onMessage(fn) {
555
+ return this.on("message", (ev) => fn(ev.message));
556
+ }
557
+ /**
558
+ * Retrieves messages from the agent's short-term (local) memory.
559
+ */
560
+ addMessage(messageInput) {
507
561
  const message = {
508
562
  ...messageInput,
509
563
  id: messageInput.id ?? randomId(),
510
564
  timestamp: messageInput.timestamp ?? Date.now(),
511
- sessionId: agent.sessionId,
512
- correlationId: messageInput.correlationId ?? randomId()
565
+ episodeId: this.episodeId
513
566
  };
514
- agent.send({
567
+ this.send({
515
568
  type: "agent.message",
516
569
  message
517
570
  });
518
571
  return message;
519
- };
520
- agent.getMessages = () => agent.getSnapshot().context.messages;
521
- agent.generateText = (opts) => agentGenerateText(agent, opts);
522
- agent.streamText = (opts) => agentStreamText(agent, opts);
523
- agent.addFeedback = (feedbackInput) => {
572
+ }
573
+ getMessages() {
574
+ return this.getSnapshot().context.messages;
575
+ }
576
+ addFeedback(feedbackInput) {
524
577
  const feedback = {
525
578
  ...feedbackInput,
526
579
  attributes: { ...feedbackInput.attributes },
527
580
  reward: feedbackInput.reward ?? 0,
528
581
  timestamp: feedbackInput.timestamp ?? Date.now(),
529
- sessionId: agent.sessionId
582
+ episodeId: this.episodeId
530
583
  };
531
- agent.send({
584
+ this.send({
532
585
  type: "agent.feedback",
533
586
  feedback
534
587
  });
535
588
  return feedback;
536
- };
537
- agent.getFeedback = () => agent.getSnapshot().context.feedback;
538
- agent.addObservation = (observationInput) => {
589
+ }
590
+ /**
591
+ * Retrieves feedback from the agent's short-term (local) memory.
592
+ */
593
+ getFeedback() {
594
+ return this.getSnapshot().context.feedback;
595
+ }
596
+ addObservation(observationInput) {
539
597
  const { prevState, event, state } = observationInput;
540
598
  const observation = {
541
599
  prevState,
542
600
  event,
543
601
  state,
544
602
  id: observationInput.id ?? randomId(),
545
- sessionId: agent.sessionId,
603
+ episodeId: this.episodeId,
546
604
  timestamp: observationInput.timestamp ?? Date.now(),
547
605
  machineHash: observationInput.machine ? getMachineHash(observationInput.machine) : void 0
548
606
  };
549
- agent.send({
607
+ this.send({
550
608
  type: "agent.observe",
551
609
  observation
552
610
  });
553
611
  return observation;
554
- };
555
- agent.getObservations = () => agent.getSnapshot().context.observations;
556
- agent.addPlan = (plan) => {
557
- agent.send({
612
+ }
613
+ /**
614
+ * Retrieves observations from the agent's short-term (local) memory.
615
+ */
616
+ getObservations() {
617
+ return this.getSnapshot().context.observations;
618
+ }
619
+ addPlan(plan) {
620
+ this.send({
558
621
  type: "agent.plan",
559
622
  plan
560
623
  });
561
- };
562
- agent.getPlans = () => agent.getSnapshot().context.plans;
563
- agent.interact = (actorRef, getInput) => {
624
+ }
625
+ /**
626
+ * Retrieves strategies from the agent's short-term (local) memory.
627
+ */
628
+ getPlans() {
629
+ return this.getSnapshot().context.plans;
630
+ }
631
+ interact(actorRef, getInput) {
632
+ const actorRefCheck = isActorRef(actorRef);
564
633
  let prevState = void 0;
565
634
  let subscribed = true;
635
+ const agent = this;
566
636
  async function handleObservation(observationInput) {
567
637
  const observation = agent.addObservation(observationInput);
568
638
  const input = getInput?.(observation);
569
639
  if (input) {
570
640
  await agentDecide(agent, {
571
- machine: actorRef.src,
641
+ machine: actorRefCheck ? actorRef.src : void 0,
572
642
  state: observation.state,
573
643
  execute: async (event) => {
574
644
  actorRef.send(event);
@@ -578,7 +648,7 @@ function createAgent({
578
648
  }
579
649
  prevState = observationInput.state;
580
650
  }
581
- actorRef.system.inspect({
651
+ const sub = actorRefCheck ? actorRef.system.inspect({
582
652
  next: async (inspEvent) => {
583
653
  if (!subscribed || inspEvent.actorRef !== actorRef || inspEvent.type !== "@xstate.snapshot") {
584
654
  return;
@@ -591,7 +661,7 @@ function createAgent({
591
661
  };
592
662
  await handleObservation(observationInput);
593
663
  }
594
- });
664
+ }) : void 0;
595
665
  if (actorRef._processingStatus === 1) {
596
666
  handleObservation({
597
667
  prevState: void 0,
@@ -603,15 +673,50 @@ function createAgent({
603
673
  }
604
674
  return {
605
675
  unsubscribe: () => {
676
+ sub?.unsubscribe();
606
677
  subscribed = false;
607
678
  }
608
- // TODO: make this actually unsubscribe
609
679
  };
610
- };
611
- agent.types = {};
612
- agent.start();
613
- return agent;
614
- }
680
+ }
681
+ observe(actorRef) {
682
+ let prevState = actorRef.getSnapshot();
683
+ const actorRefCheck = isActorRef(actorRef);
684
+ const sub = actorRefCheck ? actorRef.system.inspect({
685
+ next: async (inspEvent) => {
686
+ if (inspEvent.actorRef !== actorRef || inspEvent.type !== "@xstate.snapshot") {
687
+ return;
688
+ }
689
+ const observationInput = {
690
+ event: inspEvent.event,
691
+ prevState,
692
+ state: inspEvent.snapshot,
693
+ machine: actorRef.src
694
+ };
695
+ prevState = observationInput.state;
696
+ this.addObservation(observationInput);
697
+ }
698
+ }) : void 0;
699
+ return sub ?? { unsubscribe: () => {
700
+ } };
701
+ }
702
+ wrap(modelToWrap) {
703
+ return (0, import_ai4.experimental_wrapLanguageModel)({
704
+ model: modelToWrap,
705
+ middleware: createAgentMiddleware(this)
706
+ });
707
+ }
708
+ /**
709
+ * Resolves with an `AgentPlan` based on the information provided in the `options`, including:
710
+ *
711
+ * - The `goal` for the agent to achieve
712
+ * - The observed current `state`
713
+ * - The `machine` (e.g. a state machine) that specifies what can happen next
714
+ * - Additional `context`
715
+ */
716
+ decide(opts) {
717
+ return agentDecide(this, opts);
718
+ }
719
+ };
615
720
  // Annotate the CommonJS export names for ESM import in node:
616
721
  0 && (module.exports = {
617
722
  createAgent,