@statelyai/agent 1.0.0-beta.1 → 1.0.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.
package/dist/index.js CHANGED
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,13 +17,19 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
 
20
30
  // src/index.ts
21
31
  var src_exports = {};
22
32
  __export(src_exports, {
23
- agentDecide: () => agentDecide,
24
- agentGenerateText: () => agentGenerateText,
25
33
  createAgent: () => createAgent,
26
34
  fromDecision: () => fromDecision,
27
35
  fromText: () => fromText,
@@ -36,13 +44,36 @@ var import_xstate3 = require("xstate");
36
44
  var import_ai = require("ai");
37
45
 
38
46
  // src/utils.ts
47
+ var import_object_hash = __toESM(require("object-hash"));
39
48
  function getAllTransitions(state) {
40
49
  const nodes = state._nodes;
41
- const transitions = nodes.map((node) => [...node.transitions.values()]).flat(2).map((transition) => ({
42
- ...transition,
43
- guard: typeof transition.guard === "string" ? { type: transition.guard } : transition.guard
44
- // TODO: fix
45
- }));
50
+ const transitions = nodes.map((node) => [...node.transitions.values()]).map((nodeTransitions) => {
51
+ return nodeTransitions.map((nodeEventTransitions) => {
52
+ return nodeEventTransitions.map((transition) => {
53
+ return {
54
+ ...transition,
55
+ guard: typeof transition.guard === "string" ? { type: transition.guard } : transition.guard
56
+ // TODO: fix
57
+ };
58
+ });
59
+ });
60
+ }).flat(2);
61
+ return transitions;
62
+ }
63
+ function getAllMachineTransitions(stateNode) {
64
+ const transitions = [...stateNode.transitions.values()].map((nodeTransitions) => {
65
+ return nodeTransitions.map((transition) => {
66
+ return {
67
+ ...transition,
68
+ guard: typeof transition.guard === "string" ? { type: transition.guard } : transition.guard
69
+ // TODO: fix
70
+ };
71
+ });
72
+ }).flat(2);
73
+ for (const s of Object.values(stateNode.states)) {
74
+ const stateTransitions = getAllMachineTransitions(s);
75
+ transitions.push(...stateTransitions);
76
+ }
46
77
  return transitions;
47
78
  }
48
79
  function wrapInXml(tagName, content) {
@@ -53,6 +84,14 @@ function randomId() {
53
84
  const random = Math.random().toString(36).substring(2, 9);
54
85
  return timestamp + random;
55
86
  }
87
+ var machineHashes = /* @__PURE__ */ new WeakMap();
88
+ function getMachineHash(machine) {
89
+ if (machineHashes.has(machine)) return machineHashes.get(machine);
90
+ const transitions = getAllMachineTransitions(machine.root);
91
+ const machineHash = (0, import_object_hash.default)(transitions);
92
+ machineHashes.set(machine, machineHash);
93
+ return machineHash;
94
+ }
56
95
 
57
96
  // src/templates/defaultText.ts
58
97
  var defaultTextTemplate = (data) => {
@@ -66,94 +105,11 @@ ${data.goal}
66
105
  `.trim();
67
106
  };
68
107
 
69
- // src/planners/simplePlanner.ts
70
- function getTransitions(state, machine) {
71
- if (!machine) {
72
- return [];
73
- }
74
- const resolvedState = machine.resolveState(state);
75
- return getAllTransitions(resolvedState);
76
- }
77
- var simplePlannerPromptTemplate = (data) => {
78
- return `
79
- ${defaultTextTemplate(data)}
80
-
81
- Only make a single tool call to achieve the above goal.
82
- `.trim();
83
- };
84
- async function simplePlanner(agent, input) {
85
- const transitions = input.machine ? getTransitions(input.state, input.machine) : Object.entries(input.events).map(([eventType, { description }]) => ({
86
- eventType,
87
- description
88
- }));
89
- const filter = (eventType) => Object.keys(input.events).includes(eventType);
90
- const functionNameMapping = {};
91
- const toolTransitions = transitions.filter((t) => {
92
- return filter(t.eventType);
93
- }).map((t) => {
94
- const name = t.eventType.replace(/\./g, "_");
95
- functionNameMapping[name] = t.eventType;
96
- return {
97
- type: "function",
98
- eventType: t.eventType,
99
- description: t.description,
100
- name
101
- };
102
- });
103
- const toolMap = {};
104
- for (const toolTransitionData of toolTransitions) {
105
- const toolZodType = input.events?.[toolTransitionData.eventType];
106
- if (!toolZodType) {
107
- continue;
108
- }
109
- toolMap[toolTransitionData.name] = (0, import_ai.tool)({
110
- description: toolZodType?.description ?? toolTransitionData.description,
111
- parameters: toolZodType,
112
- execute: async (params) => {
113
- const event = {
114
- type: toolTransitionData.eventType,
115
- ...params
116
- };
117
- return event;
118
- }
119
- });
120
- }
121
- const prompt = simplePlannerPromptTemplate({
122
- context: input.state.context,
123
- goal: input.goal
124
- });
125
- const result = await agent.generateText({
126
- ...input,
127
- prompt,
128
- tools: toolMap,
129
- toolChoice: "required"
130
- });
131
- const singleResult = result.toolResults[0];
132
- if (!singleResult) {
133
- console.warn("No tool call results returned");
134
- return void 0;
135
- }
136
- return {
137
- goal: input.goal,
138
- state: input.state,
139
- steps: [
140
- {
141
- event: singleResult.result
142
- }
143
- ],
144
- nextEvent: singleResult.result,
145
- sessionId: agent.sessionId,
146
- timestamp: Date.now()
147
- };
148
- }
149
-
150
108
  // src/text.ts
151
109
  var import_xstate = require("xstate");
152
110
  async function getMessages(agent, prompt, options) {
153
111
  let messages = [];
154
- if (options.messages === true) {
155
- messages = agent.select((s) => s.messages);
156
- } else if (typeof options.messages === "function") {
112
+ if (typeof options.messages === "function") {
157
113
  messages = await options.messages(agent);
158
114
  } else if (options.messages) {
159
115
  messages = options.messages;
@@ -245,14 +201,13 @@ async function agentStreamText(agent, options) {
245
201
  return result;
246
202
  }
247
203
  function fromTextStream(agent, defaultOptions) {
248
- return (0, import_xstate.fromObservable)(({ input, self }) => {
249
- const context = input.context === true ? (self._parent?.getSnapshot()).context : input.context;
204
+ return (0, import_xstate.fromObservable)(({ input }) => {
250
205
  const observers = /* @__PURE__ */ new Set();
251
206
  (async () => {
252
207
  const result = await agentStreamText(agent, {
253
208
  ...defaultOptions,
254
209
  ...input,
255
- context
210
+ context: input.context
256
211
  });
257
212
  for await (const part of result.fullStream) {
258
213
  if (part.type === "text-delta") {
@@ -276,16 +231,103 @@ function fromTextStream(agent, defaultOptions) {
276
231
  });
277
232
  }
278
233
  function fromText(agent, defaultOptions) {
279
- return (0, import_xstate.fromPromise)(async ({ input, self }) => {
280
- const context = input.context === true ? (self._parent?.getSnapshot()).context : input.context;
234
+ return (0, import_xstate.fromPromise)(async ({ input }) => {
281
235
  return await agentGenerateText(agent, {
282
236
  ...input,
283
237
  ...defaultOptions,
284
- context
238
+ context: input.context
285
239
  });
286
240
  });
287
241
  }
288
242
 
243
+ // src/planners/simplePlanner.ts
244
+ function getTransitions(state, machine) {
245
+ if (!machine) {
246
+ return [];
247
+ }
248
+ const resolvedState = machine.resolveState(state);
249
+ return getAllTransitions(resolvedState);
250
+ }
251
+ var simplePlannerPromptTemplate = (data) => {
252
+ return `
253
+ ${defaultTextTemplate(data)}
254
+
255
+ 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.
256
+ `.trim();
257
+ };
258
+ async function simplePlanner(agent, input) {
259
+ const transitions = input.machine ? getTransitions(input.state, input.machine) : Object.entries(input.events).map(([eventType, { description }]) => ({
260
+ eventType,
261
+ description
262
+ }));
263
+ const filter = (eventType) => Object.keys(input.events).includes(eventType);
264
+ const functionNameMapping = {};
265
+ const toolTransitions = transitions.filter((t) => {
266
+ return filter(t.eventType);
267
+ }).map((t) => {
268
+ const name = t.eventType.replace(/\./g, "_");
269
+ functionNameMapping[name] = t.eventType;
270
+ return {
271
+ type: "function",
272
+ eventType: t.eventType,
273
+ description: t.description,
274
+ name
275
+ };
276
+ });
277
+ const toolMap = {};
278
+ for (const toolTransitionData of toolTransitions) {
279
+ const toolZodType = input.events?.[toolTransitionData.eventType];
280
+ if (!toolZodType) {
281
+ continue;
282
+ }
283
+ toolMap[toolTransitionData.name] = (0, import_ai.tool)({
284
+ description: toolZodType?.description ?? toolTransitionData.description,
285
+ parameters: toolZodType,
286
+ execute: async (params) => {
287
+ const event = {
288
+ type: toolTransitionData.eventType,
289
+ ...params
290
+ };
291
+ return event;
292
+ }
293
+ });
294
+ }
295
+ if (!Object.keys(toolMap).length) {
296
+ return void 0;
297
+ }
298
+ const prompt = simplePlannerPromptTemplate({
299
+ context: input.state.context,
300
+ goal: input.goal
301
+ });
302
+ const messages = await getMessages(agent, prompt, input);
303
+ const result = await agent.generateText({
304
+ toolChoice: "required",
305
+ ...input,
306
+ prompt,
307
+ messages,
308
+ tools: toolMap
309
+ });
310
+ const singleResult = result.toolResults[0];
311
+ if (!singleResult) {
312
+ console.log(toolMap);
313
+ console.warn("No tool call results returned");
314
+ return void 0;
315
+ }
316
+ return {
317
+ goal: input.goal,
318
+ state: input.state,
319
+ execute: async (state) => {
320
+ if (JSON.stringify(state) === JSON.stringify(input.state)) {
321
+ return singleResult.result;
322
+ }
323
+ return void 0;
324
+ },
325
+ nextEvent: singleResult.result,
326
+ sessionId: agent.sessionId,
327
+ timestamp: Date.now()
328
+ };
329
+ }
330
+
289
331
  // src/decision.ts
290
332
  var import_xstate2 = require("xstate");
291
333
  async function agentDecide(agent, options) {
@@ -412,6 +454,7 @@ function createAgent({
412
454
  description,
413
455
  model,
414
456
  events,
457
+ context,
415
458
  planner = simplePlanner,
416
459
  stringify = JSON.stringify,
417
460
  getMemory,
@@ -450,6 +493,7 @@ function createAgent({
450
493
  });
451
494
  return message;
452
495
  };
496
+ agent.getMessages = () => agent.getSnapshot().context.messages;
453
497
  agent.generateText = (opts) => agentGenerateText(agent, opts);
454
498
  agent.streamText = (opts) => agentStreamText(agent, opts);
455
499
  agent.addFeedback = (feedbackInput) => {
@@ -464,12 +508,17 @@ function createAgent({
464
508
  });
465
509
  return feedback;
466
510
  };
511
+ agent.getFeedback = () => agent.getSnapshot().context.feedback;
467
512
  agent.addObservation = (observationInput) => {
513
+ const { prevState, event, state } = observationInput;
468
514
  const observation = {
469
- ...observationInput,
515
+ prevState,
516
+ event,
517
+ state,
470
518
  id: observationInput.id ?? randomId(),
471
519
  sessionId: agent.sessionId,
472
- timestamp: observationInput.timestamp ?? Date.now()
520
+ timestamp: observationInput.timestamp ?? Date.now(),
521
+ machineHash: observationInput.machine ? getMachineHash(observationInput.machine) : void 0
473
522
  };
474
523
  agent.send({
475
524
  type: "agent.observe",
@@ -477,12 +526,14 @@ function createAgent({
477
526
  });
478
527
  return observation;
479
528
  };
529
+ agent.getObservations = () => agent.getSnapshot().context.observations;
480
530
  agent.addPlan = (plan) => {
481
531
  agent.send({
482
532
  type: "agent.plan",
483
533
  plan
484
534
  });
485
535
  };
536
+ agent.getPlans = () => agent.getSnapshot().context.plans;
486
537
  agent.interact = (actorRef, getInput) => {
487
538
  let prevState = void 0;
488
539
  let subscribed = true;
@@ -509,7 +560,8 @@ function createAgent({
509
560
  const observationInput = {
510
561
  event: inspEvent.event,
511
562
  prevState,
512
- state: inspEvent.snapshot
563
+ state: inspEvent.snapshot,
564
+ machine: actorRef.src
513
565
  };
514
566
  await handleObservation(observationInput);
515
567
  }
@@ -519,7 +571,8 @@ function createAgent({
519
571
  prevState: void 0,
520
572
  event: { type: "" },
521
573
  // TODO: unknown events?
522
- state: actorRef.getSnapshot()
574
+ state: actorRef.getSnapshot(),
575
+ machine: actorRef.src
523
576
  });
524
577
  }
525
578
  return {
@@ -529,13 +582,12 @@ function createAgent({
529
582
  // TODO: make this actually unsubscribe
530
583
  };
531
584
  };
585
+ agent.types = {};
532
586
  agent.start();
533
587
  return agent;
534
588
  }
535
589
  // Annotate the CommonJS export names for ESM import in node:
536
590
  0 && (module.exports = {
537
- agentDecide,
538
- agentGenerateText,
539
591
  createAgent,
540
592
  fromDecision,
541
593
  fromText,