@statelyai/agent 2.0.0-next.1 → 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/grumpy-dolphins-think.md +17 -0
- package/.changeset/old-teachers-tap.md +5 -0
- package/.changeset/pre.json +4 -1
- package/.changeset/smart-yaks-pull.md +23 -0
- package/CHANGELOG.md +40 -0
- package/dist/index.d.mts +55 -46
- package/dist/index.d.ts +55 -46
- package/dist/index.js +78 -50
- package/dist/index.mjs +81 -53
- package/examples/chatbot.ts +2 -2
- package/examples/cot.ts +6 -24
- package/examples/customer-service-sim.ts +3 -3
- package/examples/email.ts +9 -3
- package/examples/example.ts +2 -2
- package/examples/goal.ts +2 -2
- package/examples/joke.ts +2 -2
- package/examples/jugs.ts +4 -7
- package/examples/learn-from-feedback.ts +100 -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 +42 -38
- package/examples/ticTacToe.ts +46 -4
- package/examples/todo.ts +2 -2
- package/examples/tutor.ts +2 -2
- package/examples/verify.ts +2 -2
- package/examples/weather-agent.ts +141 -0
- package/examples/weather.ts +23 -23
- package/examples/word.ts +8 -6
- package/package.json +2 -1
- package/src/agent.test.ts +17 -15
- package/src/agent.ts +48 -35
- package/src/decide.test.ts +56 -8
- package/src/decide.ts +34 -24
- package/src/strategies/chainOfThought.ts +48 -0
- package/src/{planners → strategies}/shortestPath.test.ts +4 -7
- package/src/strategies/shortestPath.ts +173 -0
- package/src/{planners → strategies}/simple.ts +28 -18
- package/src/types.ts +62 -28
- package/src/utils.ts +12 -0
- package/src/planners/shortestPath.ts +0 -177
- package/src/strategies/chain-of-note.ts +0 -106
package/dist/index.mjs
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
fromTransition
|
|
5
5
|
} from "xstate";
|
|
6
6
|
|
|
7
|
-
// src/
|
|
7
|
+
// src/strategies/simple.ts
|
|
8
8
|
import { generateText as generateText2 } from "ai";
|
|
9
9
|
|
|
10
10
|
// src/utils.ts
|
|
@@ -43,6 +43,15 @@ function getAllMachineTransitions(stateNode) {
|
|
|
43
43
|
function wrapInXml(tagName, content) {
|
|
44
44
|
return `<${tagName}>${content}</${tagName}>`;
|
|
45
45
|
}
|
|
46
|
+
function convertToXml(obj) {
|
|
47
|
+
return Object.entries(obj).map(([key, value]) => {
|
|
48
|
+
if (typeof value === "object" && value !== null) {
|
|
49
|
+
return wrapInXml(key, convertToXml(value));
|
|
50
|
+
} else {
|
|
51
|
+
return wrapInXml(key, value);
|
|
52
|
+
}
|
|
53
|
+
}).join("");
|
|
54
|
+
}
|
|
46
55
|
function randomId(prefix) {
|
|
47
56
|
const timestamp = Date.now().toString(36);
|
|
48
57
|
const random = Math.random().toString(36).substring(2, 9);
|
|
@@ -74,9 +83,15 @@ function isMachineActor(actor) {
|
|
|
74
83
|
return "src" in actor && typeof actor.src === "object" && actor.src !== null && "definition" in actor.src;
|
|
75
84
|
}
|
|
76
85
|
|
|
77
|
-
// src/
|
|
86
|
+
// src/strategies/simple.ts
|
|
78
87
|
import { getNextSnapshot } from "xstate";
|
|
79
88
|
|
|
89
|
+
// src/text.ts
|
|
90
|
+
import {
|
|
91
|
+
generateText,
|
|
92
|
+
streamText
|
|
93
|
+
} from "ai";
|
|
94
|
+
|
|
80
95
|
// src/templates/defaultText.ts
|
|
81
96
|
var defaultTextTemplate = (data) => {
|
|
82
97
|
const preamble = [
|
|
@@ -90,10 +105,6 @@ ${data.goal}
|
|
|
90
105
|
};
|
|
91
106
|
|
|
92
107
|
// src/text.ts
|
|
93
|
-
import {
|
|
94
|
-
generateText,
|
|
95
|
-
streamText
|
|
96
|
-
} from "ai";
|
|
97
108
|
import {
|
|
98
109
|
fromObservable,
|
|
99
110
|
fromPromise,
|
|
@@ -186,35 +197,42 @@ async function agentDecide(agent, options) {
|
|
|
186
197
|
...options
|
|
187
198
|
};
|
|
188
199
|
const {
|
|
189
|
-
|
|
200
|
+
strategy = agent.strategy,
|
|
190
201
|
goal,
|
|
202
|
+
allowedEvents,
|
|
191
203
|
events = agent.events,
|
|
192
204
|
state,
|
|
193
205
|
machine,
|
|
194
206
|
model = agent.model,
|
|
195
207
|
messages,
|
|
196
|
-
...
|
|
208
|
+
...otherDecideInput
|
|
197
209
|
} = resolvedOptions;
|
|
210
|
+
const filteredEventSchemas = allowedEvents ? Object.fromEntries(
|
|
211
|
+
Object.entries(events).filter(([key]) => {
|
|
212
|
+
return allowedEvents.includes(key);
|
|
213
|
+
})
|
|
214
|
+
) : events;
|
|
198
215
|
let attempts = 0;
|
|
199
216
|
const maxAttempts = resolvedOptions.maxAttempts ?? 2;
|
|
200
|
-
let
|
|
217
|
+
let decision;
|
|
201
218
|
while (attempts++ < maxAttempts) {
|
|
202
|
-
|
|
219
|
+
decision = await strategy(agent, {
|
|
203
220
|
model,
|
|
204
221
|
goal,
|
|
205
|
-
events,
|
|
222
|
+
events: filteredEventSchemas,
|
|
206
223
|
state,
|
|
207
224
|
machine,
|
|
208
225
|
messages,
|
|
209
226
|
// TODO: fix UIMessage thing
|
|
210
|
-
...
|
|
227
|
+
...otherDecideInput
|
|
211
228
|
});
|
|
212
|
-
if (
|
|
213
|
-
agent.
|
|
214
|
-
await resolvedOptions.execute?.(
|
|
229
|
+
if (decision?.nextEvent) {
|
|
230
|
+
agent.addDecision(decision);
|
|
231
|
+
await resolvedOptions.execute?.(decision.nextEvent);
|
|
232
|
+
break;
|
|
215
233
|
}
|
|
216
234
|
}
|
|
217
|
-
return
|
|
235
|
+
return decision;
|
|
218
236
|
}
|
|
219
237
|
function fromDecision(agent, defaultInput) {
|
|
220
238
|
return fromPromise2(async ({ input, self }) => {
|
|
@@ -232,15 +250,18 @@ function fromDecision(agent, defaultInput) {
|
|
|
232
250
|
value: snapshot.value,
|
|
233
251
|
context: resolvedInput.context
|
|
234
252
|
};
|
|
235
|
-
const
|
|
253
|
+
const decision = await agentDecide(agent, {
|
|
236
254
|
machine: parentRef.logic,
|
|
237
|
-
state,
|
|
255
|
+
state: snapshot,
|
|
256
|
+
context: resolvedInput.context,
|
|
238
257
|
execute: async (event) => {
|
|
239
258
|
parentRef.send(event);
|
|
240
259
|
},
|
|
241
|
-
...resolvedInput
|
|
260
|
+
...resolvedInput,
|
|
261
|
+
// @ts-ignore
|
|
262
|
+
messages: resolvedInput.messages
|
|
242
263
|
});
|
|
243
|
-
return
|
|
264
|
+
return decision;
|
|
244
265
|
});
|
|
245
266
|
}
|
|
246
267
|
function getToolMap(_agent, input) {
|
|
@@ -286,37 +307,38 @@ function getToolMap(_agent, input) {
|
|
|
286
307
|
return toolMap;
|
|
287
308
|
}
|
|
288
309
|
|
|
289
|
-
// src/
|
|
290
|
-
var
|
|
310
|
+
// src/strategies/simple.ts
|
|
311
|
+
var simpleStrategyPromptTemplate = (data) => {
|
|
291
312
|
return `
|
|
292
|
-
${
|
|
313
|
+
${convertToXml(data)}
|
|
293
314
|
|
|
294
315
|
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.
|
|
295
316
|
`.trim();
|
|
296
317
|
};
|
|
297
|
-
async function
|
|
318
|
+
async function simpleStrategy(agent, input) {
|
|
298
319
|
const toolMap = getToolMap(agent, input);
|
|
299
320
|
if (!toolMap) {
|
|
300
321
|
return void 0;
|
|
301
322
|
}
|
|
302
|
-
const prompt =
|
|
303
|
-
context: input.
|
|
323
|
+
const prompt = simpleStrategyPromptTemplate({
|
|
324
|
+
context: input.context,
|
|
304
325
|
goal: input.goal
|
|
305
326
|
});
|
|
306
327
|
const messages = await getMessages(agent, prompt, input);
|
|
307
328
|
const model = input.model ? agent.wrap(input.model) : agent.model;
|
|
308
329
|
const {
|
|
309
330
|
state,
|
|
331
|
+
context,
|
|
310
332
|
machine,
|
|
311
|
-
|
|
333
|
+
prevDecision,
|
|
312
334
|
events,
|
|
313
335
|
goal,
|
|
314
336
|
model: _,
|
|
315
337
|
...rest
|
|
316
338
|
} = input;
|
|
317
|
-
const machineState = input.machine ? input.machine.resolveState({
|
|
339
|
+
const machineState = input.machine && input.state ? input.machine.resolveState({
|
|
318
340
|
...input.state,
|
|
319
|
-
context: input.state.context
|
|
341
|
+
context: input.state.context ?? {}
|
|
320
342
|
}) : void 0;
|
|
321
343
|
const result = await generateText2({
|
|
322
344
|
...rest,
|
|
@@ -340,7 +362,7 @@ async function simplePlanner(agent, input) {
|
|
|
340
362
|
return void 0;
|
|
341
363
|
}
|
|
342
364
|
return {
|
|
343
|
-
|
|
365
|
+
strategy: "simple",
|
|
344
366
|
goal: input.goal,
|
|
345
367
|
goalState: input.state,
|
|
346
368
|
nextEvent: singleResult.result,
|
|
@@ -459,12 +481,11 @@ var agentLogic = fromTransition(
|
|
|
459
481
|
});
|
|
460
482
|
break;
|
|
461
483
|
}
|
|
462
|
-
case "agent.
|
|
463
|
-
state.
|
|
484
|
+
case "agent.decision": {
|
|
485
|
+
state.decisions.push(event.decision);
|
|
464
486
|
emit({
|
|
465
|
-
type: "
|
|
466
|
-
|
|
467
|
-
plan: event.plan
|
|
487
|
+
type: "decision",
|
|
488
|
+
decision: event.decision
|
|
468
489
|
});
|
|
469
490
|
break;
|
|
470
491
|
}
|
|
@@ -479,7 +500,7 @@ var agentLogic = fromTransition(
|
|
|
479
500
|
feedback: [],
|
|
480
501
|
messages: [],
|
|
481
502
|
observations: [],
|
|
482
|
-
|
|
503
|
+
decisions: []
|
|
483
504
|
})
|
|
484
505
|
);
|
|
485
506
|
function createAgent({
|
|
@@ -488,7 +509,8 @@ function createAgent({
|
|
|
488
509
|
model,
|
|
489
510
|
events,
|
|
490
511
|
context,
|
|
491
|
-
|
|
512
|
+
episodeId,
|
|
513
|
+
strategy = simpleStrategy,
|
|
492
514
|
logic = agentLogic
|
|
493
515
|
}) {
|
|
494
516
|
return new Agent({
|
|
@@ -496,9 +518,10 @@ function createAgent({
|
|
|
496
518
|
context,
|
|
497
519
|
events,
|
|
498
520
|
description,
|
|
499
|
-
|
|
521
|
+
strategy,
|
|
500
522
|
model,
|
|
501
|
-
logic
|
|
523
|
+
logic,
|
|
524
|
+
episodeId
|
|
502
525
|
});
|
|
503
526
|
}
|
|
504
527
|
var Agent = class extends Actor {
|
|
@@ -511,17 +534,18 @@ var Agent = class extends Actor {
|
|
|
511
534
|
model,
|
|
512
535
|
events,
|
|
513
536
|
context,
|
|
514
|
-
|
|
537
|
+
episodeId,
|
|
538
|
+
strategy = simpleStrategy
|
|
515
539
|
}) {
|
|
516
540
|
super(logic);
|
|
517
541
|
this.model = model;
|
|
518
|
-
this.episodeId =
|
|
542
|
+
this.episodeId = episodeId ?? randomId("episode-");
|
|
519
543
|
this.name = name;
|
|
520
544
|
this.description = description;
|
|
521
545
|
this.events = events;
|
|
522
546
|
this.context = context;
|
|
523
|
-
this.
|
|
524
|
-
this.
|
|
547
|
+
this.strategy = strategy;
|
|
548
|
+
this.id = id ?? randomId();
|
|
525
549
|
this.start();
|
|
526
550
|
}
|
|
527
551
|
/**
|
|
@@ -530,6 +554,12 @@ var Agent = class extends Actor {
|
|
|
530
554
|
onMessage(fn) {
|
|
531
555
|
return this.on("message", (ev) => fn(ev.message));
|
|
532
556
|
}
|
|
557
|
+
/**
|
|
558
|
+
* Called whenever the agent (LLM assistant) receives some feedback.
|
|
559
|
+
*/
|
|
560
|
+
onFeedback(fn) {
|
|
561
|
+
return this.on("feedback", (ev) => fn(ev.feedback));
|
|
562
|
+
}
|
|
533
563
|
/**
|
|
534
564
|
* Retrieves messages from the agent's short-term (local) memory.
|
|
535
565
|
*/
|
|
@@ -553,7 +583,6 @@ var Agent = class extends Actor {
|
|
|
553
583
|
const feedback = {
|
|
554
584
|
...feedbackInput,
|
|
555
585
|
attributes: { ...feedbackInput.attributes },
|
|
556
|
-
reward: feedbackInput.reward ?? 0,
|
|
557
586
|
timestamp: feedbackInput.timestamp ?? Date.now(),
|
|
558
587
|
episodeId: this.episodeId
|
|
559
588
|
};
|
|
@@ -592,17 +621,17 @@ var Agent = class extends Actor {
|
|
|
592
621
|
getObservations() {
|
|
593
622
|
return this.getSnapshot().context.observations;
|
|
594
623
|
}
|
|
595
|
-
|
|
624
|
+
addDecision(decision) {
|
|
596
625
|
this.send({
|
|
597
|
-
type: "agent.
|
|
598
|
-
|
|
626
|
+
type: "agent.decision",
|
|
627
|
+
decision
|
|
599
628
|
});
|
|
600
629
|
}
|
|
601
630
|
/**
|
|
602
631
|
* Retrieves strategies from the agent's short-term (local) memory.
|
|
603
632
|
*/
|
|
604
|
-
|
|
605
|
-
return this.getSnapshot().context.
|
|
633
|
+
getDecisions() {
|
|
634
|
+
return this.getSnapshot().context.decisions;
|
|
606
635
|
}
|
|
607
636
|
interact(actorRef, getInput) {
|
|
608
637
|
const actorRefCheck = isActorRef(actorRef) && actorRef.src;
|
|
@@ -642,8 +671,7 @@ var Agent = class extends Actor {
|
|
|
642
671
|
if (actorRef._processingStatus === 1) {
|
|
643
672
|
handleObservation({
|
|
644
673
|
prevState: void 0,
|
|
645
|
-
event:
|
|
646
|
-
// TODO: unknown events?
|
|
674
|
+
event: void 0,
|
|
647
675
|
state: actorRef.getSnapshot(),
|
|
648
676
|
machine: actorRef.src
|
|
649
677
|
});
|
|
@@ -683,14 +711,14 @@ var Agent = class extends Actor {
|
|
|
683
711
|
});
|
|
684
712
|
}
|
|
685
713
|
/**
|
|
686
|
-
* Resolves with an `
|
|
714
|
+
* Resolves with an `AgentDecision` based on the information provided in the `options`, including:
|
|
687
715
|
*
|
|
688
716
|
* - The `goal` for the agent to achieve
|
|
689
717
|
* - The observed current `state`
|
|
690
718
|
* - The `machine` (e.g. a state machine) that specifies what can happen next
|
|
691
719
|
* - Additional `context`
|
|
692
720
|
*/
|
|
693
|
-
decide(opts) {
|
|
721
|
+
async decide(opts) {
|
|
694
722
|
return agentDecide(this, opts);
|
|
695
723
|
}
|
|
696
724
|
};
|
package/examples/chatbot.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { createAgent, fromDecision } from '../src';
|
|
2
|
+
import { createAgent, fromDecision, TypesFromAgent } from '../src';
|
|
3
3
|
import { openai } from '@ai-sdk/openai';
|
|
4
4
|
import { assign, createActor, log, setup } from 'xstate';
|
|
5
5
|
import { fromTerminal } from './helpers/helpers';
|
|
@@ -19,7 +19,7 @@ const agent = createAgent({
|
|
|
19
19
|
});
|
|
20
20
|
|
|
21
21
|
const machine = setup({
|
|
22
|
-
types: agent
|
|
22
|
+
types: {} as TypesFromAgent<typeof agent>,
|
|
23
23
|
actors: { getFromTerminal: fromTerminal },
|
|
24
24
|
}).createMachine({
|
|
25
25
|
initial: 'listening',
|
package/examples/cot.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { createAgent, fromDecision } from '../src';
|
|
2
|
+
import { createAgent, fromDecision, TypesFromAgent } from '../src';
|
|
3
3
|
import { openai } from '@ai-sdk/openai';
|
|
4
4
|
import { assign, createActor, log, setup } from 'xstate';
|
|
5
5
|
import { fromTerminal } from './helpers/helpers';
|
|
6
|
+
import { chainOfThoughtStrategy } from '../src/strategies/chainOfThought';
|
|
6
7
|
|
|
7
8
|
const agent = createAgent({
|
|
8
9
|
id: 'chain-of-thought',
|
|
@@ -19,18 +20,17 @@ const agent = createAgent({
|
|
|
19
20
|
},
|
|
20
21
|
context: {
|
|
21
22
|
question: z.string().nullable(),
|
|
22
|
-
thought: z.string().nullable(),
|
|
23
23
|
},
|
|
24
|
+
strategy: chainOfThoughtStrategy,
|
|
24
25
|
});
|
|
25
26
|
|
|
26
27
|
const machine = setup({
|
|
27
|
-
types: agent
|
|
28
|
+
types: {} as TypesFromAgent<typeof agent>,
|
|
28
29
|
actors: { getFromTerminal: fromTerminal },
|
|
29
30
|
}).createMachine({
|
|
30
31
|
initial: 'asking',
|
|
31
32
|
context: {
|
|
32
33
|
question: null,
|
|
33
|
-
thought: null,
|
|
34
34
|
},
|
|
35
35
|
states: {
|
|
36
36
|
asking: {
|
|
@@ -41,19 +41,6 @@ const machine = setup({
|
|
|
41
41
|
actions: assign({
|
|
42
42
|
question: ({ event }) => event.output,
|
|
43
43
|
}),
|
|
44
|
-
target: 'thinking',
|
|
45
|
-
},
|
|
46
|
-
},
|
|
47
|
-
},
|
|
48
|
-
thinking: {
|
|
49
|
-
on: {
|
|
50
|
-
'agent.think': {
|
|
51
|
-
actions: [
|
|
52
|
-
log(({ event }) => `Thought: ${event.thought}`),
|
|
53
|
-
assign({
|
|
54
|
-
thought: ({ event }) => event.thought,
|
|
55
|
-
}),
|
|
56
|
-
],
|
|
57
44
|
target: 'answering',
|
|
58
45
|
},
|
|
59
46
|
},
|
|
@@ -74,14 +61,9 @@ const machine = setup({
|
|
|
74
61
|
|
|
75
62
|
const actor = createActor(machine).start();
|
|
76
63
|
|
|
64
|
+
agent.onMessage(console.log);
|
|
65
|
+
|
|
77
66
|
agent.interact(actor, (obs) => {
|
|
78
|
-
if (obs.state.matches('thinking')) {
|
|
79
|
-
return {
|
|
80
|
-
goal: 'Think step-by-step about how you would answer the question',
|
|
81
|
-
context: obs.state.context,
|
|
82
|
-
messages: agent.getMessages(),
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
67
|
if (obs.state.matches('answering')) {
|
|
86
68
|
return {
|
|
87
69
|
goal: 'Answer the question',
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createAgent, fromDecision } from '../src';
|
|
1
|
+
import { createAgent, EventsFromAgent, fromDecision } from '../src';
|
|
2
2
|
import { assign, createActor, setup } from 'xstate';
|
|
3
3
|
import { openai } from '@ai-sdk/openai';
|
|
4
4
|
import { z } from 'zod';
|
|
@@ -38,8 +38,8 @@ const machine = setup({
|
|
|
38
38
|
messages: string[];
|
|
39
39
|
},
|
|
40
40
|
events: {} as
|
|
41
|
-
| typeof customerServiceAgent
|
|
42
|
-
| typeof customerAgent
|
|
41
|
+
| EventsFromAgent<typeof customerServiceAgent>
|
|
42
|
+
| EventsFromAgent<typeof customerAgent>,
|
|
43
43
|
},
|
|
44
44
|
actors: {
|
|
45
45
|
customerService: fromDecision(customerServiceAgent),
|
package/examples/email.ts
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
ContextFromAgent,
|
|
4
|
+
createAgent,
|
|
5
|
+
EventsFromAgent,
|
|
6
|
+
fromDecision,
|
|
7
|
+
TypesFromAgent,
|
|
8
|
+
} from '../src';
|
|
3
9
|
import { openai } from '@ai-sdk/openai';
|
|
4
10
|
import { assign, createActor, setup } from 'xstate';
|
|
5
11
|
import { fromTerminal } from './helpers/helpers';
|
|
@@ -27,12 +33,12 @@ const agent = createAgent({
|
|
|
27
33
|
|
|
28
34
|
const machine = setup({
|
|
29
35
|
types: {
|
|
30
|
-
events: agent
|
|
36
|
+
events: {} as EventsFromAgent<typeof agent>,
|
|
31
37
|
input: {} as {
|
|
32
38
|
email: string;
|
|
33
39
|
instructions: string;
|
|
34
40
|
},
|
|
35
|
-
context: agent
|
|
41
|
+
context: {} as ContextFromAgent<typeof agent>,
|
|
36
42
|
},
|
|
37
43
|
actors: { getFromTerminal: fromTerminal },
|
|
38
44
|
}).createMachine({
|
package/examples/example.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { createAgent, fromDecision, fromText } from '../src';
|
|
2
|
+
import { createAgent, EventsFromAgent, fromDecision, fromText } from '../src';
|
|
3
3
|
import { openai } from '@ai-sdk/openai';
|
|
4
4
|
import { assign, createActor, setup } from 'xstate';
|
|
5
5
|
|
|
@@ -18,7 +18,7 @@ const agent = createAgent({
|
|
|
18
18
|
|
|
19
19
|
const machine = setup({
|
|
20
20
|
types: {
|
|
21
|
-
events: agent
|
|
21
|
+
events: {} as EventsFromAgent<typeof agent>,
|
|
22
22
|
},
|
|
23
23
|
actors: { agent: fromDecision(agent), summarizer: fromText(agent) },
|
|
24
24
|
}).createMachine({
|
package/examples/goal.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { createAgent, fromDecision } from '../src';
|
|
2
|
+
import { createAgent, EventsFromAgent, fromDecision } from '../src';
|
|
3
3
|
import { openai } from '@ai-sdk/openai';
|
|
4
4
|
import { assign, createActor, log, setup } from 'xstate';
|
|
5
5
|
import { fromTerminal } from './helpers/helpers';
|
|
@@ -25,7 +25,7 @@ const machine = setup({
|
|
|
25
25
|
question: string | null;
|
|
26
26
|
goal: string | null;
|
|
27
27
|
},
|
|
28
|
-
events: agent
|
|
28
|
+
events: {} as EventsFromAgent<typeof agent>,
|
|
29
29
|
},
|
|
30
30
|
actors: { decider, getFromTerminal: fromTerminal },
|
|
31
31
|
}).createMachine({
|
package/examples/joke.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { assign, createActor, fromCallback, log, setup } from 'xstate';
|
|
2
|
-
import { createAgent, fromDecision } from '../src';
|
|
2
|
+
import { createAgent, fromDecision, TypesFromAgent } from '../src';
|
|
3
3
|
import { loadingAnimation } from './helpers/loader';
|
|
4
4
|
import { z } from 'zod';
|
|
5
5
|
import { openai } from '@ai-sdk/openai';
|
|
@@ -81,7 +81,7 @@ const agent = createAgent({
|
|
|
81
81
|
});
|
|
82
82
|
|
|
83
83
|
const jokeMachine = setup({
|
|
84
|
-
types: agent
|
|
84
|
+
types: {} as TypesFromAgent<typeof agent>,
|
|
85
85
|
actors: {
|
|
86
86
|
agent: fromDecision(agent),
|
|
87
87
|
loader,
|
package/examples/jugs.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { createAgent } from '../src';
|
|
1
|
+
import { createAgent, TypesFromAgent } from '../src';
|
|
2
2
|
import { assign, createActor, setup } from 'xstate';
|
|
3
3
|
import { openai } from '@ai-sdk/openai';
|
|
4
4
|
import { z } from 'zod';
|
|
5
|
-
import {
|
|
5
|
+
import { experimental_shortestPathStrategy } from '../src/strategies/shortestPath';
|
|
6
6
|
|
|
7
7
|
const agent = createAgent({
|
|
8
8
|
id: 'die-hard-solver',
|
|
@@ -38,10 +38,7 @@ const agent = createAgent({
|
|
|
38
38
|
});
|
|
39
39
|
|
|
40
40
|
const waterJugMachine = setup({
|
|
41
|
-
types: {
|
|
42
|
-
context: agent.types.context,
|
|
43
|
-
events: agent.types.events,
|
|
44
|
-
},
|
|
41
|
+
types: {} as TypesFromAgent<typeof agent>,
|
|
45
42
|
}).createMachine({
|
|
46
43
|
initial: 'solving',
|
|
47
44
|
context: { jug3: 0, jug5: 0 },
|
|
@@ -106,7 +103,7 @@ async function main() {
|
|
|
106
103
|
machine: waterJugMachine,
|
|
107
104
|
goal: 'Get exactly 4 gallons of water in the 5-gallon jug',
|
|
108
105
|
state: waterJugActor.getSnapshot(),
|
|
109
|
-
|
|
106
|
+
strategy: experimental_shortestPathStrategy,
|
|
110
107
|
});
|
|
111
108
|
|
|
112
109
|
console.log(decision?.nextEvent);
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { createAgent } from '../src';
|
|
3
|
+
import { openai } from '@ai-sdk/openai';
|
|
4
|
+
|
|
5
|
+
const agent = createAgent({
|
|
6
|
+
id: 'chatbot',
|
|
7
|
+
model: openai('gpt-4o-mini'),
|
|
8
|
+
events: {
|
|
9
|
+
submit: z.object({}).describe('Submit the form'),
|
|
10
|
+
pressEnter: z.object({}).describe('Press the enter key'),
|
|
11
|
+
},
|
|
12
|
+
context: {
|
|
13
|
+
userMessage: z.string(),
|
|
14
|
+
},
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
agent.onMessage((msg) => {
|
|
18
|
+
console.log(`Message`, msg.content);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
agent.on('decision', ({ decision }) => {
|
|
22
|
+
console.log(`Decision: ${decision.nextEvent?.type ?? '??'}`);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
async function main() {
|
|
26
|
+
let status = 'editing';
|
|
27
|
+
let count = 0;
|
|
28
|
+
|
|
29
|
+
while (status !== 'submitted') {
|
|
30
|
+
console.log(`Attempt ${count} - ${status}`);
|
|
31
|
+
if (count++ > 5) {
|
|
32
|
+
break;
|
|
33
|
+
}
|
|
34
|
+
switch (status) {
|
|
35
|
+
case 'editing': {
|
|
36
|
+
const relevantObservations = await agent
|
|
37
|
+
.getObservations()
|
|
38
|
+
.filter((obs) => obs.prevState.value === 'editing');
|
|
39
|
+
const relevantFeedback = await agent
|
|
40
|
+
.getFeedback()
|
|
41
|
+
.filter((f) =>
|
|
42
|
+
relevantObservations.find((o) => o.id === f.observationId)
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
const decision = await agent.decide({
|
|
46
|
+
goal: 'Submit the form. Take the feedback into consideration, and perform the action that will lead to the form being submitted.',
|
|
47
|
+
state: {
|
|
48
|
+
value: 'editing',
|
|
49
|
+
context: {
|
|
50
|
+
feedback: relevantFeedback.map((f) => {
|
|
51
|
+
const observation = relevantObservations.find(
|
|
52
|
+
(o) => o.id === f.observationId
|
|
53
|
+
);
|
|
54
|
+
return {
|
|
55
|
+
prevState: observation?.prevState,
|
|
56
|
+
event: observation?.event,
|
|
57
|
+
state: observation?.state,
|
|
58
|
+
feedback: f.attributes.text,
|
|
59
|
+
};
|
|
60
|
+
}),
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
if (decision?.nextEvent?.type === 'submit') {
|
|
66
|
+
const observation = await agent.addObservation({
|
|
67
|
+
prevState: { value: 'editing' },
|
|
68
|
+
event: { type: 'submit' },
|
|
69
|
+
state: { value: 'editing' },
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// don't change the status; pretend submit button is broken
|
|
73
|
+
await agent.addFeedback({
|
|
74
|
+
observationId: observation.id,
|
|
75
|
+
goal: 'Submit the form',
|
|
76
|
+
attributes: {
|
|
77
|
+
text: 'Form not submitted',
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
} else if (decision?.nextEvent?.type === 'pressEnter') {
|
|
81
|
+
status = 'submitted';
|
|
82
|
+
|
|
83
|
+
await agent.addObservation({
|
|
84
|
+
prevState: { value: 'editing' },
|
|
85
|
+
event: { type: 'pressEnter' },
|
|
86
|
+
state: { value: 'submitted' },
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
case 'submitted':
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
console.log('End of conversation.');
|
|
97
|
+
process.exit();
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
main().catch(console.error);
|
package/examples/number.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createAgent, fromDecision } from '../src';
|
|
1
|
+
import { createAgent, EventsFromAgent, fromDecision } from '../src';
|
|
2
2
|
import { assign, createActor, log, setup } from 'xstate';
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
import { openai } from '@ai-sdk/openai';
|
|
@@ -21,7 +21,7 @@ const machine = setup({
|
|
|
21
21
|
previousGuesses: number[];
|
|
22
22
|
answer: number | null;
|
|
23
23
|
},
|
|
24
|
-
events: agent
|
|
24
|
+
events: {} as EventsFromAgent<typeof agent>,
|
|
25
25
|
},
|
|
26
26
|
actors: {
|
|
27
27
|
agent: fromDecision(agent),
|
package/examples/raffle.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { createAgent, fromDecision } from '../src';
|
|
2
|
+
import { createAgent, EventsFromAgent, fromDecision } from '../src';
|
|
3
3
|
import { openai } from '@ai-sdk/openai';
|
|
4
4
|
import { assign, createActor, log, setup } from 'xstate';
|
|
5
5
|
import { fromTerminal } from './helpers/helpers';
|
|
@@ -27,7 +27,7 @@ const machine = setup({
|
|
|
27
27
|
lastInput: string | null;
|
|
28
28
|
entries: string[];
|
|
29
29
|
},
|
|
30
|
-
events: agent
|
|
30
|
+
events: {} as EventsFromAgent<typeof agent>,
|
|
31
31
|
},
|
|
32
32
|
actors: { agent: fromDecision(agent), getFromTerminal: fromTerminal },
|
|
33
33
|
}).createMachine({
|