@statelyai/agent 2.0.0-next.1 → 2.0.0-next.3
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/grumpy-dolphins-think.md +17 -0
- package/.changeset/old-teachers-tap.md +5 -0
- package/.changeset/pink-eagles-deliver.md +13 -0
- package/.changeset/pre.json +9 -1
- package/.changeset/quiet-turtles-do.md +7 -0
- package/.changeset/smart-yaks-pull.md +23 -0
- package/.changeset/sweet-clouds-mix.md +16 -0
- package/.changeset/swift-mangos-rush.md +5 -0
- package/.changeset/tough-ways-rhyme.md +5 -0
- package/CHANGELOG.md +79 -0
- package/dist/index.d.mts +116 -100
- package/dist/index.d.ts +116 -100
- package/dist/index.js +102 -72
- package/dist/index.mjs +105 -75
- package/examples/chatbot.ts +2 -2
- package/examples/cot.ts +21 -73
- package/examples/customer-service-sim.ts +3 -3
- package/examples/email.ts +3 -5
- package/examples/example.ts +2 -2
- package/examples/goal.ts +2 -2
- package/examples/joke.ts +12 -12
- package/examples/jugs.ts +4 -7
- package/examples/learn-from-feedback.ts +123 -0
- package/examples/number.ts +2 -2
- package/examples/raffle.ts +2 -2
- package/examples/river-crossing.ts +4 -7
- package/examples/simple.ts +13 -10
- package/examples/summary.ts +2 -5
- package/examples/support.ts +38 -38
- package/examples/ticTacToe.ts +46 -4
- package/examples/todo.ts +3 -3
- package/examples/tutor.ts +2 -2
- package/examples/verify.ts +2 -2
- package/examples/weather-agent.ts +139 -0
- package/examples/weather.ts +26 -23
- package/examples/word.ts +8 -6
- package/package.json +2 -1
- package/src/agent.test.ts +37 -52
- package/src/agent.ts +93 -60
- package/src/decide.test.ts +56 -8
- package/src/decide.ts +42 -32
- package/src/strategies/chainOfThought.ts +50 -0
- package/src/{planners → strategies}/shortestPath.test.ts +4 -7
- package/src/strategies/shortestPath.ts +178 -0
- package/src/{planners → strategies}/simple.ts +25 -26
- package/src/templates/defaultText.ts +3 -0
- package/src/text.ts +13 -13
- package/src/types.ts +124 -83
- package/src/utils.ts +13 -1
- package/src/planners/shortestPath.ts +0 -177
- package/src/strategies/chain-of-note.ts +0 -106
package/dist/index.js
CHANGED
|
@@ -40,7 +40,7 @@ module.exports = __toCommonJS(src_exports);
|
|
|
40
40
|
// src/agent.ts
|
|
41
41
|
var import_xstate4 = require("xstate");
|
|
42
42
|
|
|
43
|
-
// src/
|
|
43
|
+
// src/strategies/simple.ts
|
|
44
44
|
var import_ai3 = require("ai");
|
|
45
45
|
|
|
46
46
|
// src/utils.ts
|
|
@@ -79,6 +79,15 @@ function getAllMachineTransitions(stateNode) {
|
|
|
79
79
|
function wrapInXml(tagName, content) {
|
|
80
80
|
return `<${tagName}>${content}</${tagName}>`;
|
|
81
81
|
}
|
|
82
|
+
function convertToXml(obj) {
|
|
83
|
+
return Object.entries(obj).map(([key, value]) => {
|
|
84
|
+
if (typeof value === "object" && value !== null) {
|
|
85
|
+
return wrapInXml(key, convertToXml(value));
|
|
86
|
+
} else {
|
|
87
|
+
return wrapInXml(key, value);
|
|
88
|
+
}
|
|
89
|
+
}).join("");
|
|
90
|
+
}
|
|
82
91
|
function randomId(prefix) {
|
|
83
92
|
const timestamp = Date.now().toString(36);
|
|
84
93
|
const random = Math.random().toString(36).substring(2, 9);
|
|
@@ -110,12 +119,16 @@ function isMachineActor(actor) {
|
|
|
110
119
|
return "src" in actor && typeof actor.src === "object" && actor.src !== null && "definition" in actor.src;
|
|
111
120
|
}
|
|
112
121
|
|
|
113
|
-
// src/
|
|
122
|
+
// src/strategies/simple.ts
|
|
114
123
|
var import_xstate3 = require("xstate");
|
|
115
124
|
|
|
125
|
+
// src/text.ts
|
|
126
|
+
var import_ai = require("ai");
|
|
127
|
+
|
|
116
128
|
// src/templates/defaultText.ts
|
|
117
129
|
var defaultTextTemplate = (data) => {
|
|
118
130
|
const preamble = [
|
|
131
|
+
data.stateValue ? wrapInXml("stateValue", JSON.stringify(data.stateValue)) : void 0,
|
|
119
132
|
data.context ? wrapInXml("context", JSON.stringify(data.context)) : void 0
|
|
120
133
|
].filter(Boolean).join("\n");
|
|
121
134
|
return `
|
|
@@ -126,7 +139,6 @@ ${data.goal}
|
|
|
126
139
|
};
|
|
127
140
|
|
|
128
141
|
// src/text.ts
|
|
129
|
-
var import_ai = require("ai");
|
|
130
142
|
var import_xstate = require("xstate");
|
|
131
143
|
async function getMessages(agent, prompt, options) {
|
|
132
144
|
let messages = [];
|
|
@@ -215,35 +227,46 @@ async function agentDecide(agent, options) {
|
|
|
215
227
|
...options
|
|
216
228
|
};
|
|
217
229
|
const {
|
|
218
|
-
|
|
230
|
+
strategy = agent.strategy,
|
|
219
231
|
goal,
|
|
232
|
+
allowedEvents,
|
|
220
233
|
events = agent.events,
|
|
221
234
|
state,
|
|
222
235
|
machine,
|
|
223
236
|
model = agent.model,
|
|
224
237
|
messages,
|
|
225
|
-
...
|
|
238
|
+
...otherDecideInput
|
|
226
239
|
} = resolvedOptions;
|
|
240
|
+
const filteredEventSchemas = allowedEvents ? Object.fromEntries(
|
|
241
|
+
Object.entries(events).filter(([key]) => {
|
|
242
|
+
return allowedEvents.includes(key);
|
|
243
|
+
})
|
|
244
|
+
) : events;
|
|
227
245
|
let attempts = 0;
|
|
228
246
|
const maxAttempts = resolvedOptions.maxAttempts ?? 2;
|
|
229
|
-
let
|
|
247
|
+
let decision;
|
|
248
|
+
const minimalState = {
|
|
249
|
+
value: state.value,
|
|
250
|
+
context: state.context
|
|
251
|
+
};
|
|
230
252
|
while (attempts++ < maxAttempts) {
|
|
231
|
-
|
|
253
|
+
decision = await strategy(agent, {
|
|
232
254
|
model,
|
|
233
255
|
goal,
|
|
234
|
-
events,
|
|
235
|
-
state,
|
|
256
|
+
events: filteredEventSchemas,
|
|
257
|
+
state: minimalState,
|
|
236
258
|
machine,
|
|
237
259
|
messages,
|
|
238
260
|
// TODO: fix UIMessage thing
|
|
239
|
-
...
|
|
261
|
+
...otherDecideInput
|
|
240
262
|
});
|
|
241
|
-
if (
|
|
242
|
-
agent.
|
|
243
|
-
await resolvedOptions.execute?.(
|
|
263
|
+
if (decision?.nextEvent) {
|
|
264
|
+
agent.addDecision(decision);
|
|
265
|
+
await resolvedOptions.execute?.(decision.nextEvent);
|
|
266
|
+
break;
|
|
244
267
|
}
|
|
245
268
|
}
|
|
246
|
-
return
|
|
269
|
+
return decision;
|
|
247
270
|
}
|
|
248
271
|
function fromDecision(agent, defaultInput) {
|
|
249
272
|
return (0, import_xstate2.fromPromise)(async ({ input, self }) => {
|
|
@@ -257,19 +280,17 @@ function fromDecision(agent, defaultInput) {
|
|
|
257
280
|
...defaultInput,
|
|
258
281
|
...inputObject
|
|
259
282
|
};
|
|
260
|
-
const
|
|
261
|
-
value: snapshot.value,
|
|
262
|
-
context: resolvedInput.context
|
|
263
|
-
};
|
|
264
|
-
const plan = await agentDecide(agent, {
|
|
283
|
+
const decision = await agentDecide(agent, {
|
|
265
284
|
machine: parentRef.logic,
|
|
266
|
-
state,
|
|
285
|
+
state: snapshot,
|
|
267
286
|
execute: async (event) => {
|
|
268
287
|
parentRef.send(event);
|
|
269
288
|
},
|
|
270
|
-
...resolvedInput
|
|
289
|
+
...resolvedInput,
|
|
290
|
+
// @ts-ignore
|
|
291
|
+
messages: resolvedInput.messages
|
|
271
292
|
});
|
|
272
|
-
return
|
|
293
|
+
return decision;
|
|
273
294
|
});
|
|
274
295
|
}
|
|
275
296
|
function getToolMap(_agent, input) {
|
|
@@ -315,37 +336,30 @@ function getToolMap(_agent, input) {
|
|
|
315
336
|
return toolMap;
|
|
316
337
|
}
|
|
317
338
|
|
|
318
|
-
// src/
|
|
319
|
-
var
|
|
339
|
+
// src/strategies/simple.ts
|
|
340
|
+
var simpleStrategyPromptTemplate = (data) => {
|
|
320
341
|
return `
|
|
321
|
-
${
|
|
342
|
+
${convertToXml(data)}
|
|
322
343
|
|
|
323
344
|
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.
|
|
324
345
|
`.trim();
|
|
325
346
|
};
|
|
326
|
-
async function
|
|
347
|
+
async function simpleStrategy(agent, input) {
|
|
327
348
|
const toolMap = getToolMap(agent, input);
|
|
328
349
|
if (!toolMap) {
|
|
329
350
|
return void 0;
|
|
330
351
|
}
|
|
331
|
-
const prompt =
|
|
332
|
-
|
|
352
|
+
const prompt = simpleStrategyPromptTemplate({
|
|
353
|
+
stateValue: input.state.value,
|
|
354
|
+
context: input.context ?? input.state.context,
|
|
333
355
|
goal: input.goal
|
|
334
356
|
});
|
|
335
357
|
const messages = await getMessages(agent, prompt, input);
|
|
336
358
|
const model = input.model ? agent.wrap(input.model) : agent.model;
|
|
337
|
-
const {
|
|
338
|
-
|
|
339
|
-
machine,
|
|
340
|
-
previousPlan,
|
|
341
|
-
events,
|
|
342
|
-
goal,
|
|
343
|
-
model: _,
|
|
344
|
-
...rest
|
|
345
|
-
} = input;
|
|
346
|
-
const machineState = input.machine ? input.machine.resolveState({
|
|
359
|
+
const { state, machine, events, goal, model: _, ...rest } = input;
|
|
360
|
+
const machineState = input.machine && input.state ? input.machine.resolveState({
|
|
347
361
|
...input.state,
|
|
348
|
-
context: input.state.context
|
|
362
|
+
context: input.state.context ?? {}
|
|
349
363
|
}) : void 0;
|
|
350
364
|
const result = await (0, import_ai3.generateText)({
|
|
351
365
|
...rest,
|
|
@@ -369,7 +383,8 @@ async function simplePlanner(agent, input) {
|
|
|
369
383
|
return void 0;
|
|
370
384
|
}
|
|
371
385
|
return {
|
|
372
|
-
|
|
386
|
+
id: randomId(),
|
|
387
|
+
strategy: "simple",
|
|
373
388
|
goal: input.goal,
|
|
374
389
|
goalState: input.state,
|
|
375
390
|
nextEvent: singleResult.result,
|
|
@@ -486,12 +501,11 @@ var agentLogic = (0, import_xstate4.fromTransition)(
|
|
|
486
501
|
});
|
|
487
502
|
break;
|
|
488
503
|
}
|
|
489
|
-
case "agent.
|
|
490
|
-
state.
|
|
504
|
+
case "agent.decision": {
|
|
505
|
+
state.decisions.push(event.decision);
|
|
491
506
|
emit({
|
|
492
|
-
type: "
|
|
493
|
-
|
|
494
|
-
plan: event.plan
|
|
507
|
+
type: "decision",
|
|
508
|
+
decision: event.decision
|
|
495
509
|
});
|
|
496
510
|
break;
|
|
497
511
|
}
|
|
@@ -506,7 +520,7 @@ var agentLogic = (0, import_xstate4.fromTransition)(
|
|
|
506
520
|
feedback: [],
|
|
507
521
|
messages: [],
|
|
508
522
|
observations: [],
|
|
509
|
-
|
|
523
|
+
decisions: []
|
|
510
524
|
})
|
|
511
525
|
);
|
|
512
526
|
function createAgent({
|
|
@@ -515,7 +529,8 @@ function createAgent({
|
|
|
515
529
|
model,
|
|
516
530
|
events,
|
|
517
531
|
context,
|
|
518
|
-
|
|
532
|
+
episodeId,
|
|
533
|
+
strategy = simpleStrategy,
|
|
519
534
|
logic = agentLogic
|
|
520
535
|
}) {
|
|
521
536
|
return new Agent({
|
|
@@ -523,9 +538,10 @@ function createAgent({
|
|
|
523
538
|
context,
|
|
524
539
|
events,
|
|
525
540
|
description,
|
|
526
|
-
|
|
541
|
+
strategy,
|
|
527
542
|
model,
|
|
528
|
-
logic
|
|
543
|
+
logic,
|
|
544
|
+
episodeId
|
|
529
545
|
});
|
|
530
546
|
}
|
|
531
547
|
var Agent = class extends import_xstate4.Actor {
|
|
@@ -538,17 +554,18 @@ var Agent = class extends import_xstate4.Actor {
|
|
|
538
554
|
model,
|
|
539
555
|
events,
|
|
540
556
|
context,
|
|
541
|
-
|
|
557
|
+
episodeId,
|
|
558
|
+
strategy = simpleStrategy
|
|
542
559
|
}) {
|
|
543
560
|
super(logic);
|
|
544
561
|
this.model = model;
|
|
545
|
-
this.episodeId =
|
|
562
|
+
this.episodeId = episodeId ?? randomId("episode-");
|
|
546
563
|
this.name = name;
|
|
547
564
|
this.description = description;
|
|
548
565
|
this.events = events;
|
|
549
566
|
this.context = context;
|
|
550
|
-
this.
|
|
551
|
-
this.
|
|
567
|
+
this.strategy = strategy;
|
|
568
|
+
this.id = id ?? randomId();
|
|
552
569
|
this.start();
|
|
553
570
|
}
|
|
554
571
|
/**
|
|
@@ -557,6 +574,12 @@ var Agent = class extends import_xstate4.Actor {
|
|
|
557
574
|
onMessage(fn) {
|
|
558
575
|
return this.on("message", (ev) => fn(ev.message));
|
|
559
576
|
}
|
|
577
|
+
/**
|
|
578
|
+
* Called whenever the agent (LLM assistant) receives some feedback.
|
|
579
|
+
*/
|
|
580
|
+
onFeedback(fn) {
|
|
581
|
+
return this.on("feedback", (ev) => fn(ev.feedback));
|
|
582
|
+
}
|
|
560
583
|
/**
|
|
561
584
|
* Retrieves messages from the agent's short-term (local) memory.
|
|
562
585
|
*/
|
|
@@ -579,8 +602,8 @@ var Agent = class extends import_xstate4.Actor {
|
|
|
579
602
|
addFeedback(feedbackInput) {
|
|
580
603
|
const feedback = {
|
|
581
604
|
...feedbackInput,
|
|
605
|
+
comment: feedbackInput.comment ?? void 0,
|
|
582
606
|
attributes: { ...feedbackInput.attributes },
|
|
583
|
-
reward: feedbackInput.reward ?? 0,
|
|
584
607
|
timestamp: feedbackInput.timestamp ?? Date.now(),
|
|
585
608
|
episodeId: this.episodeId
|
|
586
609
|
};
|
|
@@ -619,17 +642,17 @@ var Agent = class extends import_xstate4.Actor {
|
|
|
619
642
|
getObservations() {
|
|
620
643
|
return this.getSnapshot().context.observations;
|
|
621
644
|
}
|
|
622
|
-
|
|
645
|
+
addDecision(decision) {
|
|
623
646
|
this.send({
|
|
624
|
-
type: "agent.
|
|
625
|
-
|
|
647
|
+
type: "agent.decision",
|
|
648
|
+
decision
|
|
626
649
|
});
|
|
627
650
|
}
|
|
628
651
|
/**
|
|
629
652
|
* Retrieves strategies from the agent's short-term (local) memory.
|
|
630
653
|
*/
|
|
631
|
-
|
|
632
|
-
return this.getSnapshot().context.
|
|
654
|
+
getDecisions() {
|
|
655
|
+
return this.getSnapshot().context.decisions;
|
|
633
656
|
}
|
|
634
657
|
interact(actorRef, getInput) {
|
|
635
658
|
const actorRefCheck = isActorRef(actorRef) && actorRef.src;
|
|
@@ -639,15 +662,16 @@ var Agent = class extends import_xstate4.Actor {
|
|
|
639
662
|
const agent = this;
|
|
640
663
|
async function handleObservation(observationInput) {
|
|
641
664
|
const observation = agent.addObservation(observationInput);
|
|
642
|
-
const
|
|
643
|
-
if (
|
|
644
|
-
const
|
|
665
|
+
const interactInput = getInput?.(observation);
|
|
666
|
+
if (interactInput) {
|
|
667
|
+
const decision = await agentDecide(agent, {
|
|
645
668
|
machine,
|
|
646
669
|
state: observation.state,
|
|
647
|
-
...
|
|
670
|
+
...interactInput
|
|
648
671
|
});
|
|
649
|
-
if (
|
|
650
|
-
|
|
672
|
+
if (decision?.nextEvent) {
|
|
673
|
+
decision.nextEvent["_decision"] = decision.id;
|
|
674
|
+
actorRef.send(decision.nextEvent);
|
|
651
675
|
}
|
|
652
676
|
}
|
|
653
677
|
prevState = observationInput.state;
|
|
@@ -657,11 +681,14 @@ var Agent = class extends import_xstate4.Actor {
|
|
|
657
681
|
if (!subscribed || inspEvent.actorRef !== actorRef || inspEvent.type !== "@xstate.snapshot") {
|
|
658
682
|
return;
|
|
659
683
|
}
|
|
684
|
+
const decisionId = inspEvent.event["_decision"];
|
|
685
|
+
const decision = decisionId ? agent.getDecisions().find((d) => d.id === decisionId) : void 0;
|
|
660
686
|
const observationInput = {
|
|
661
687
|
event: inspEvent.event,
|
|
662
688
|
prevState,
|
|
663
689
|
state: inspEvent.snapshot,
|
|
664
|
-
machine: actorRef.src
|
|
690
|
+
machine: actorRef.src,
|
|
691
|
+
goal: decision?.goal
|
|
665
692
|
};
|
|
666
693
|
await handleObservation(observationInput);
|
|
667
694
|
}
|
|
@@ -669,10 +696,10 @@ var Agent = class extends import_xstate4.Actor {
|
|
|
669
696
|
if (actorRef._processingStatus === 1) {
|
|
670
697
|
handleObservation({
|
|
671
698
|
prevState: void 0,
|
|
672
|
-
event:
|
|
673
|
-
// TODO: unknown events?
|
|
699
|
+
event: void 0,
|
|
674
700
|
state: actorRef.getSnapshot(),
|
|
675
|
-
machine: actorRef.src
|
|
701
|
+
machine: actorRef.src,
|
|
702
|
+
goal: void 0
|
|
676
703
|
});
|
|
677
704
|
}
|
|
678
705
|
return {
|
|
@@ -690,11 +717,14 @@ var Agent = class extends import_xstate4.Actor {
|
|
|
690
717
|
if (inspEvent.actorRef !== actorRef || inspEvent.type !== "@xstate.snapshot") {
|
|
691
718
|
return;
|
|
692
719
|
}
|
|
720
|
+
const decisionId = inspEvent.event["_decision"];
|
|
721
|
+
const decision = decisionId ? this.getDecisions().find((d) => d.id === decisionId) : void 0;
|
|
693
722
|
const observationInput = {
|
|
694
723
|
event: inspEvent.event,
|
|
695
724
|
prevState,
|
|
696
725
|
state: inspEvent.snapshot,
|
|
697
|
-
machine: actorRef.src
|
|
726
|
+
machine: actorRef.src,
|
|
727
|
+
goal: decision?.goal
|
|
698
728
|
};
|
|
699
729
|
prevState = observationInput.state;
|
|
700
730
|
this.addObservation(observationInput);
|
|
@@ -710,14 +740,14 @@ var Agent = class extends import_xstate4.Actor {
|
|
|
710
740
|
});
|
|
711
741
|
}
|
|
712
742
|
/**
|
|
713
|
-
* Resolves with an `
|
|
743
|
+
* Resolves with an `AgentDecision` based on the information provided in the `options`, including:
|
|
714
744
|
*
|
|
715
745
|
* - The `goal` for the agent to achieve
|
|
716
746
|
* - The observed current `state`
|
|
717
747
|
* - The `machine` (e.g. a state machine) that specifies what can happen next
|
|
718
748
|
* - Additional `context`
|
|
719
749
|
*/
|
|
720
|
-
decide(opts) {
|
|
750
|
+
async decide(opts) {
|
|
721
751
|
return agentDecide(this, opts);
|
|
722
752
|
}
|
|
723
753
|
};
|