@statelyai/agent 2.0.0-next.0 → 2.0.0-next.2
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/cyan-carpets-perform.md +5 -0
- package/.changeset/fast-donkeys-argue.md +5 -0
- package/.changeset/grumpy-dolphins-think.md +17 -0
- package/.changeset/old-jobs-check.md +5 -0
- package/.changeset/old-teachers-tap.md +5 -0
- package/.changeset/pre.json +7 -1
- package/.changeset/smart-yaks-pull.md +23 -0
- package/CHANGELOG.md +52 -0
- package/dist/index.d.mts +69 -66
- package/dist/index.d.ts +69 -66
- package/dist/index.js +111 -79
- package/dist/index.mjs +114 -82
- package/examples/chatbot-alt.ts +1 -1
- package/examples/chatbot.ts +3 -3
- package/examples/cot.ts +7 -25
- package/examples/customer-service-sim.ts +7 -7
- package/examples/email.ts +37 -35
- package/examples/example.ts +3 -3
- package/examples/goal.ts +3 -3
- package/examples/joke.ts +3 -3
- package/examples/jugs.ts +5 -8
- package/examples/learn-from-feedback.ts +100 -0
- package/examples/multi.ts +1 -1
- package/examples/number.ts +3 -3
- package/examples/raffle.ts +3 -3
- package/examples/river-crossing.ts +5 -8
- package/examples/simple.ts +14 -11
- package/examples/summary.ts +3 -6
- package/examples/support.ts +43 -39
- package/examples/ticTacToe.ts +48 -6
- package/examples/todo.ts +3 -3
- package/examples/tutor.ts +4 -4
- package/examples/verify.ts +3 -3
- package/examples/weather-agent.ts +141 -0
- package/examples/weather.ts +24 -24
- package/examples/wiki.ts +1 -1
- package/examples/word.ts +9 -7
- package/package.json +6 -3
- package/src/agent.test.ts +161 -19
- package/src/agent.ts +66 -250
- package/src/decide.test.ts +172 -3
- package/src/decide.ts +50 -30
- package/src/middleware.ts +2 -14
- package/src/strategies/chainOfThought.ts +48 -0
- package/src/strategies/shortestPath.test.ts +91 -0
- package/src/{planners/shortestPathPlanner.ts → strategies/shortestPath.ts} +32 -19
- package/src/{planners/simplePlanner.ts → strategies/simple.ts} +28 -24
- package/src/types.ts +75 -34
- package/src/utils.ts +23 -0
- package/vitest.config.ts +9 -3
- 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);
|
|
@@ -106,10 +115,16 @@ function getTransitions(state, machine) {
|
|
|
106
115
|
});
|
|
107
116
|
return getAllTransitions(resolvedState);
|
|
108
117
|
}
|
|
118
|
+
function isMachineActor(actor) {
|
|
119
|
+
return "src" in actor && typeof actor.src === "object" && actor.src !== null && "definition" in actor.src;
|
|
120
|
+
}
|
|
109
121
|
|
|
110
|
-
// src/
|
|
122
|
+
// src/strategies/simple.ts
|
|
111
123
|
var import_xstate3 = require("xstate");
|
|
112
124
|
|
|
125
|
+
// src/text.ts
|
|
126
|
+
var import_ai = require("ai");
|
|
127
|
+
|
|
113
128
|
// src/templates/defaultText.ts
|
|
114
129
|
var defaultTextTemplate = (data) => {
|
|
115
130
|
const preamble = [
|
|
@@ -123,7 +138,6 @@ ${data.goal}
|
|
|
123
138
|
};
|
|
124
139
|
|
|
125
140
|
// src/text.ts
|
|
126
|
-
var import_ai = require("ai");
|
|
127
141
|
var import_xstate = require("xstate");
|
|
128
142
|
async function getMessages(agent, prompt, options) {
|
|
129
143
|
let messages = [];
|
|
@@ -212,27 +226,42 @@ async function agentDecide(agent, options) {
|
|
|
212
226
|
...options
|
|
213
227
|
};
|
|
214
228
|
const {
|
|
215
|
-
|
|
229
|
+
strategy = agent.strategy,
|
|
216
230
|
goal,
|
|
231
|
+
allowedEvents,
|
|
217
232
|
events = agent.events,
|
|
218
233
|
state,
|
|
219
234
|
machine,
|
|
220
235
|
model = agent.model,
|
|
221
|
-
|
|
236
|
+
messages,
|
|
237
|
+
...otherDecideInput
|
|
222
238
|
} = resolvedOptions;
|
|
223
|
-
const
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
agent
|
|
233
|
-
|
|
239
|
+
const filteredEventSchemas = allowedEvents ? Object.fromEntries(
|
|
240
|
+
Object.entries(events).filter(([key]) => {
|
|
241
|
+
return allowedEvents.includes(key);
|
|
242
|
+
})
|
|
243
|
+
) : events;
|
|
244
|
+
let attempts = 0;
|
|
245
|
+
const maxAttempts = resolvedOptions.maxAttempts ?? 2;
|
|
246
|
+
let decision;
|
|
247
|
+
while (attempts++ < maxAttempts) {
|
|
248
|
+
decision = await strategy(agent, {
|
|
249
|
+
model,
|
|
250
|
+
goal,
|
|
251
|
+
events: filteredEventSchemas,
|
|
252
|
+
state,
|
|
253
|
+
machine,
|
|
254
|
+
messages,
|
|
255
|
+
// TODO: fix UIMessage thing
|
|
256
|
+
...otherDecideInput
|
|
257
|
+
});
|
|
258
|
+
if (decision?.nextEvent) {
|
|
259
|
+
agent.addDecision(decision);
|
|
260
|
+
await resolvedOptions.execute?.(decision.nextEvent);
|
|
261
|
+
break;
|
|
262
|
+
}
|
|
234
263
|
}
|
|
235
|
-
return
|
|
264
|
+
return decision;
|
|
236
265
|
}
|
|
237
266
|
function fromDecision(agent, defaultInput) {
|
|
238
267
|
return (0, import_xstate2.fromPromise)(async ({ input, self }) => {
|
|
@@ -250,15 +279,18 @@ function fromDecision(agent, defaultInput) {
|
|
|
250
279
|
value: snapshot.value,
|
|
251
280
|
context: resolvedInput.context
|
|
252
281
|
};
|
|
253
|
-
const
|
|
282
|
+
const decision = await agentDecide(agent, {
|
|
254
283
|
machine: parentRef.logic,
|
|
255
|
-
state,
|
|
284
|
+
state: snapshot,
|
|
285
|
+
context: resolvedInput.context,
|
|
256
286
|
execute: async (event) => {
|
|
257
287
|
parentRef.send(event);
|
|
258
288
|
},
|
|
259
|
-
...resolvedInput
|
|
289
|
+
...resolvedInput,
|
|
290
|
+
// @ts-ignore
|
|
291
|
+
messages: resolvedInput.messages
|
|
260
292
|
});
|
|
261
|
-
return
|
|
293
|
+
return decision;
|
|
262
294
|
});
|
|
263
295
|
}
|
|
264
296
|
function getToolMap(_agent, input) {
|
|
@@ -304,46 +336,48 @@ function getToolMap(_agent, input) {
|
|
|
304
336
|
return toolMap;
|
|
305
337
|
}
|
|
306
338
|
|
|
307
|
-
// src/
|
|
308
|
-
var
|
|
339
|
+
// src/strategies/simple.ts
|
|
340
|
+
var simpleStrategyPromptTemplate = (data) => {
|
|
309
341
|
return `
|
|
310
|
-
${
|
|
342
|
+
${convertToXml(data)}
|
|
311
343
|
|
|
312
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.
|
|
313
345
|
`.trim();
|
|
314
346
|
};
|
|
315
|
-
async function
|
|
347
|
+
async function simpleStrategy(agent, input) {
|
|
316
348
|
const toolMap = getToolMap(agent, input);
|
|
317
349
|
if (!toolMap) {
|
|
318
350
|
return void 0;
|
|
319
351
|
}
|
|
320
|
-
const prompt =
|
|
321
|
-
context: input.
|
|
352
|
+
const prompt = simpleStrategyPromptTemplate({
|
|
353
|
+
context: input.context,
|
|
322
354
|
goal: input.goal
|
|
323
355
|
});
|
|
324
356
|
const messages = await getMessages(agent, prompt, input);
|
|
325
357
|
const model = input.model ? agent.wrap(input.model) : agent.model;
|
|
326
358
|
const {
|
|
327
359
|
state,
|
|
360
|
+
context,
|
|
328
361
|
machine,
|
|
329
|
-
|
|
362
|
+
prevDecision,
|
|
330
363
|
events,
|
|
331
364
|
goal,
|
|
332
365
|
model: _,
|
|
333
366
|
...rest
|
|
334
367
|
} = input;
|
|
335
|
-
const machineState = input.machine ? input.machine.resolveState({
|
|
368
|
+
const machineState = input.machine && input.state ? input.machine.resolveState({
|
|
336
369
|
...input.state,
|
|
337
|
-
context: input.state.context
|
|
370
|
+
context: input.state.context ?? {}
|
|
338
371
|
}) : void 0;
|
|
339
372
|
const result = await (0, import_ai3.generateText)({
|
|
340
373
|
...rest,
|
|
374
|
+
system: input.system ?? agent.description,
|
|
341
375
|
model,
|
|
342
376
|
messages,
|
|
343
377
|
tools: toolMap,
|
|
344
378
|
toolChoice: input.toolChoice ?? "required"
|
|
345
379
|
});
|
|
346
|
-
result.
|
|
380
|
+
result.response.messages.forEach((m) => {
|
|
347
381
|
const message = m;
|
|
348
382
|
agent.addMessage({
|
|
349
383
|
...message,
|
|
@@ -357,7 +391,7 @@ async function simplePlanner(agent, input) {
|
|
|
357
391
|
return void 0;
|
|
358
392
|
}
|
|
359
393
|
return {
|
|
360
|
-
|
|
394
|
+
strategy: "simple",
|
|
361
395
|
goal: input.goal,
|
|
362
396
|
goalState: input.state,
|
|
363
397
|
nextEvent: singleResult.result,
|
|
@@ -388,13 +422,11 @@ function createAgentMiddleware(agent) {
|
|
|
388
422
|
},
|
|
389
423
|
wrapGenerate: async ({ doGenerate, params }) => {
|
|
390
424
|
const id = randomId();
|
|
391
|
-
params.prompt.forEach((
|
|
425
|
+
params.prompt.forEach((message) => {
|
|
392
426
|
agent.addMessage({
|
|
393
427
|
id,
|
|
394
|
-
...
|
|
395
|
-
timestamp: Date.now()
|
|
396
|
-
correlationId: params.providerMetadata?.correlationId,
|
|
397
|
-
parentCorrelationId: params.providerMetadata?.parentCorrelationId
|
|
428
|
+
...message,
|
|
429
|
+
timestamp: Date.now()
|
|
398
430
|
});
|
|
399
431
|
});
|
|
400
432
|
const result = await doGenerate();
|
|
@@ -407,9 +439,7 @@ function createAgentMiddleware(agent) {
|
|
|
407
439
|
agent.addMessage({
|
|
408
440
|
id,
|
|
409
441
|
...message,
|
|
410
|
-
timestamp: Date.now()
|
|
411
|
-
correlationId: params.providerMetadata?.correlationId,
|
|
412
|
-
parentCorrelationId: params.providerMetadata?.parentCorrelationId
|
|
442
|
+
timestamp: Date.now()
|
|
413
443
|
});
|
|
414
444
|
});
|
|
415
445
|
const { stream, ...rest } = await doStream();
|
|
@@ -434,9 +464,7 @@ function createAgentMiddleware(agent) {
|
|
|
434
464
|
timestamp: Date.now(),
|
|
435
465
|
role: "assistant",
|
|
436
466
|
content,
|
|
437
|
-
responseId: id
|
|
438
|
-
correlationId: params.providerMetadata?.correlationId,
|
|
439
|
-
parentCorrelationId: params.providerMetadata?.parentCorrelationId
|
|
467
|
+
responseId: id
|
|
440
468
|
});
|
|
441
469
|
}
|
|
442
470
|
});
|
|
@@ -480,17 +508,18 @@ var agentLogic = (0, import_xstate4.fromTransition)(
|
|
|
480
508
|
});
|
|
481
509
|
break;
|
|
482
510
|
}
|
|
483
|
-
case "agent.
|
|
484
|
-
state.
|
|
511
|
+
case "agent.decision": {
|
|
512
|
+
state.decisions.push(event.decision);
|
|
485
513
|
emit({
|
|
486
|
-
type: "
|
|
487
|
-
|
|
488
|
-
plan: event.plan
|
|
514
|
+
type: "decision",
|
|
515
|
+
decision: event.decision
|
|
489
516
|
});
|
|
490
517
|
break;
|
|
491
518
|
}
|
|
492
|
-
default:
|
|
519
|
+
default: {
|
|
520
|
+
console.warn("Unrecognized event", event);
|
|
493
521
|
break;
|
|
522
|
+
}
|
|
494
523
|
}
|
|
495
524
|
return state;
|
|
496
525
|
},
|
|
@@ -498,31 +527,28 @@ var agentLogic = (0, import_xstate4.fromTransition)(
|
|
|
498
527
|
feedback: [],
|
|
499
528
|
messages: [],
|
|
500
529
|
observations: [],
|
|
501
|
-
|
|
530
|
+
decisions: []
|
|
502
531
|
})
|
|
503
532
|
);
|
|
504
533
|
function createAgent({
|
|
505
534
|
id,
|
|
506
|
-
name,
|
|
507
535
|
description,
|
|
508
536
|
model,
|
|
509
537
|
events,
|
|
510
538
|
context,
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
logic = agentLogic,
|
|
515
|
-
...generateTextOptions
|
|
539
|
+
episodeId,
|
|
540
|
+
strategy = simpleStrategy,
|
|
541
|
+
logic = agentLogic
|
|
516
542
|
}) {
|
|
517
543
|
return new Agent({
|
|
518
544
|
id,
|
|
519
545
|
context,
|
|
520
546
|
events,
|
|
521
|
-
name,
|
|
522
547
|
description,
|
|
523
|
-
|
|
548
|
+
strategy,
|
|
524
549
|
model,
|
|
525
|
-
logic
|
|
550
|
+
logic,
|
|
551
|
+
episodeId
|
|
526
552
|
});
|
|
527
553
|
}
|
|
528
554
|
var Agent = class extends import_xstate4.Actor {
|
|
@@ -535,17 +561,18 @@ var Agent = class extends import_xstate4.Actor {
|
|
|
535
561
|
model,
|
|
536
562
|
events,
|
|
537
563
|
context,
|
|
538
|
-
|
|
564
|
+
episodeId,
|
|
565
|
+
strategy = simpleStrategy
|
|
539
566
|
}) {
|
|
540
567
|
super(logic);
|
|
541
568
|
this.model = model;
|
|
542
|
-
this.episodeId =
|
|
569
|
+
this.episodeId = episodeId ?? randomId("episode-");
|
|
543
570
|
this.name = name;
|
|
544
571
|
this.description = description;
|
|
545
572
|
this.events = events;
|
|
546
573
|
this.context = context;
|
|
547
|
-
this.
|
|
548
|
-
this.
|
|
574
|
+
this.strategy = strategy;
|
|
575
|
+
this.id = id ?? randomId();
|
|
549
576
|
this.start();
|
|
550
577
|
}
|
|
551
578
|
/**
|
|
@@ -554,6 +581,12 @@ var Agent = class extends import_xstate4.Actor {
|
|
|
554
581
|
onMessage(fn) {
|
|
555
582
|
return this.on("message", (ev) => fn(ev.message));
|
|
556
583
|
}
|
|
584
|
+
/**
|
|
585
|
+
* Called whenever the agent (LLM assistant) receives some feedback.
|
|
586
|
+
*/
|
|
587
|
+
onFeedback(fn) {
|
|
588
|
+
return this.on("feedback", (ev) => fn(ev.feedback));
|
|
589
|
+
}
|
|
557
590
|
/**
|
|
558
591
|
* Retrieves messages from the agent's short-term (local) memory.
|
|
559
592
|
*/
|
|
@@ -577,7 +610,6 @@ var Agent = class extends import_xstate4.Actor {
|
|
|
577
610
|
const feedback = {
|
|
578
611
|
...feedbackInput,
|
|
579
612
|
attributes: { ...feedbackInput.attributes },
|
|
580
|
-
reward: feedbackInput.reward ?? 0,
|
|
581
613
|
timestamp: feedbackInput.timestamp ?? Date.now(),
|
|
582
614
|
episodeId: this.episodeId
|
|
583
615
|
};
|
|
@@ -616,20 +648,21 @@ var Agent = class extends import_xstate4.Actor {
|
|
|
616
648
|
getObservations() {
|
|
617
649
|
return this.getSnapshot().context.observations;
|
|
618
650
|
}
|
|
619
|
-
|
|
651
|
+
addDecision(decision) {
|
|
620
652
|
this.send({
|
|
621
|
-
type: "agent.
|
|
622
|
-
|
|
653
|
+
type: "agent.decision",
|
|
654
|
+
decision
|
|
623
655
|
});
|
|
624
656
|
}
|
|
625
657
|
/**
|
|
626
658
|
* Retrieves strategies from the agent's short-term (local) memory.
|
|
627
659
|
*/
|
|
628
|
-
|
|
629
|
-
return this.getSnapshot().context.
|
|
660
|
+
getDecisions() {
|
|
661
|
+
return this.getSnapshot().context.decisions;
|
|
630
662
|
}
|
|
631
663
|
interact(actorRef, getInput) {
|
|
632
|
-
const actorRefCheck = isActorRef(actorRef);
|
|
664
|
+
const actorRefCheck = isActorRef(actorRef) && actorRef.src;
|
|
665
|
+
const machine = isMachineActor(actorRef) ? actorRef.src : void 0;
|
|
633
666
|
let prevState = void 0;
|
|
634
667
|
let subscribed = true;
|
|
635
668
|
const agent = this;
|
|
@@ -637,14 +670,14 @@ var Agent = class extends import_xstate4.Actor {
|
|
|
637
670
|
const observation = agent.addObservation(observationInput);
|
|
638
671
|
const input = getInput?.(observation);
|
|
639
672
|
if (input) {
|
|
640
|
-
await agentDecide(agent, {
|
|
641
|
-
machine
|
|
673
|
+
const res = await agentDecide(agent, {
|
|
674
|
+
machine,
|
|
642
675
|
state: observation.state,
|
|
643
|
-
execute: async (event) => {
|
|
644
|
-
actorRef.send(event);
|
|
645
|
-
},
|
|
646
676
|
...input
|
|
647
677
|
});
|
|
678
|
+
if (res?.nextEvent) {
|
|
679
|
+
actorRef.send(res.nextEvent);
|
|
680
|
+
}
|
|
648
681
|
}
|
|
649
682
|
prevState = observationInput.state;
|
|
650
683
|
}
|
|
@@ -665,8 +698,7 @@ var Agent = class extends import_xstate4.Actor {
|
|
|
665
698
|
if (actorRef._processingStatus === 1) {
|
|
666
699
|
handleObservation({
|
|
667
700
|
prevState: void 0,
|
|
668
|
-
event:
|
|
669
|
-
// TODO: unknown events?
|
|
701
|
+
event: void 0,
|
|
670
702
|
state: actorRef.getSnapshot(),
|
|
671
703
|
machine: actorRef.src
|
|
672
704
|
});
|
|
@@ -706,14 +738,14 @@ var Agent = class extends import_xstate4.Actor {
|
|
|
706
738
|
});
|
|
707
739
|
}
|
|
708
740
|
/**
|
|
709
|
-
* Resolves with an `
|
|
741
|
+
* Resolves with an `AgentDecision` based on the information provided in the `options`, including:
|
|
710
742
|
*
|
|
711
743
|
* - The `goal` for the agent to achieve
|
|
712
744
|
* - The observed current `state`
|
|
713
745
|
* - The `machine` (e.g. a state machine) that specifies what can happen next
|
|
714
746
|
* - Additional `context`
|
|
715
747
|
*/
|
|
716
|
-
decide(opts) {
|
|
748
|
+
async decide(opts) {
|
|
717
749
|
return agentDecide(this, opts);
|
|
718
750
|
}
|
|
719
751
|
};
|