@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/.changeset/heavy-moons-bake.md +12 -0
- package/.changeset/silly-berries-drop.md +5 -0
- package/.changeset/wild-bobcats-care.md +26 -0
- package/.env.template +0 -3
- package/.github/workflows/release.yml +3 -3
- package/dist/index.d.mts +135 -44
- package/dist/index.d.ts +135 -44
- package/dist/index.js +155 -103
- package/dist/index.mjs +145 -101
- package/examples/chatbot.ts +9 -17
- package/examples/cot.ts +5 -7
- package/examples/email.ts +2 -2
- package/examples/example.ts +7 -7
- package/examples/goal.ts +1 -1
- package/examples/joke.ts +8 -10
- package/examples/number.ts +1 -1
- package/examples/raffle.ts +1 -1
- package/examples/sandbox.ts +28 -0
- package/examples/support.ts +1 -1
- package/examples/ticTacToe.ts +18 -21
- package/examples/todo.ts +3 -1
- package/examples/tutor.ts +1 -1
- package/examples/verify.ts +1 -1
- package/examples/weather.ts +1 -1
- package/examples/wiki.ts +1 -1
- package/examples/word.ts +1 -1
- package/package.json +8 -6
- package/src/agent.test.ts +176 -4
- package/src/agent.ts +51 -16
- package/src/decision.ts +6 -5
- package/src/index.ts +2 -2
- package/src/planners/shortestPathPlanner.ts +2 -2
- package/src/planners/simplePlanner.ts +22 -11
- package/src/schemas.ts +4 -8
- package/src/strategies/chain-of-note.ts +3 -3
- package/src/text.ts +15 -27
- package/src/types.ts +114 -32
- package/src/utils.ts +53 -9
- package/src/templates/defaultToolCall.ts +0 -10
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()]).
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
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 ===
|
|
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
|
|
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
|
|
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
|
-
|
|
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,
|