@statelyai/agent 1.1.6 → 2.0.0-alpha.10
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/LICENSE +21 -0
- package/dist/ai-sdk.cjs +342 -0
- package/dist/ai-sdk.d.cts +206 -0
- package/dist/ai-sdk.d.mts +206 -0
- package/dist/ai-sdk.mjs +331 -0
- package/dist/cli.cjs +64 -0
- package/dist/cli.d.cts +1 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.mjs +65 -0
- package/dist/decision-CQdrKc8k.mjs +978 -0
- package/dist/decision-b-lkcs4L.cjs +1295 -0
- package/dist/index.cjs +59 -0
- package/dist/index.d.cts +212 -0
- package/dist/index.d.mts +201 -417
- package/dist/index.mjs +4 -588
- package/dist/openai-compat.cjs +319 -0
- package/dist/openai-compat.d.cts +98 -0
- package/dist/openai-compat.d.mts +98 -0
- package/dist/openai-compat.mjs +312 -0
- package/dist/run-agent-BFMkuI1F.cjs +1599 -0
- package/dist/run-agent-BVMd--1l.d.cts +1103 -0
- package/dist/run-agent-BoAOq_0Z.mjs +1540 -0
- package/dist/run-agent-DzYJb3CK.d.mts +1103 -0
- package/dist/src-D-77Ha5p.cjs +1087 -0
- package/dist/src-DUeIFjv-.mjs +1016 -0
- package/dist/text-logic-C7WJpCIc.d.mts +710 -0
- package/dist/text-logic-CZjyACzQ.d.cts +710 -0
- package/dist/types-C9QiMjre.d.cts +219 -0
- package/dist/types-qm00QF91.d.mts +219 -0
- package/dist/utils-Dri7aeEG.d.cts +108 -0
- package/dist/utils-Y6GDRGGE.d.mts +108 -0
- package/dist/zod.cjs +31 -0
- package/dist/zod.d.cts +30 -0
- package/dist/zod.d.mts +30 -0
- package/dist/zod.mjs +30 -0
- package/package.json +109 -28
- package/readme.md +143 -6
- package/schemas/agent-workflow.json +527 -0
- package/.changeset/README.md +0 -8
- package/.changeset/config.json +0 -11
- package/.env.template +0 -3
- package/.github/actions/ci-setup/action.yml +0 -24
- package/.github/workflows/release.yml +0 -46
- package/.vscode/launch.json +0 -28
- package/CHANGELOG.md +0 -222
- package/dist/index.d.ts +0 -428
- package/dist/index.js +0 -621
- package/examples/chatbot.ts +0 -71
- package/examples/cot.ts +0 -89
- package/examples/email.ts +0 -118
- package/examples/example.ts +0 -81
- package/examples/goal.ts +0 -94
- package/examples/helpers/helpers.ts +0 -17
- package/examples/helpers/loader.ts +0 -32
- package/examples/helpers/runner.ts +0 -27
- package/examples/joke.ts +0 -225
- package/examples/multi.ts +0 -103
- package/examples/newspaper.ts +0 -324
- package/examples/number.ts +0 -102
- package/examples/raffle.ts +0 -105
- package/examples/sandbox.ts +0 -28
- package/examples/simple.ts +0 -39
- package/examples/support.ts +0 -147
- package/examples/ticTacToe.ts +0 -224
- package/examples/todo.ts +0 -137
- package/examples/tutor.ts +0 -100
- package/examples/verify.ts +0 -120
- package/examples/weather.ts +0 -178
- package/examples/wiki.ts +0 -30
- package/examples/word.ts +0 -171
- package/src/adapters/vercel.ts +0 -7
- package/src/agent-experimental.ts +0 -221
- package/src/agent.test.ts +0 -506
- package/src/agent.ts +0 -300
- package/src/decision.test.ts +0 -179
- package/src/decision.ts +0 -84
- package/src/index.ts +0 -4
- package/src/memory.ts +0 -25
- package/src/planners/shortestPathPlanner.ts +0 -22
- package/src/planners/simplePlanner.ts +0 -139
- package/src/schemas.ts +0 -11
- package/src/strategies/chain-of-note.ts +0 -155
- package/src/templates/defaultText.ts +0 -18
- package/src/text.ts +0 -241
- package/src/types.ts +0 -499
- package/src/utils.ts +0 -72
- package/tsconfig.json +0 -109
- package/vitest.config.ts +0 -9
package/src/agent.ts
DELETED
|
@@ -1,300 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
AnyEventObject,
|
|
3
|
-
AnyStateMachine,
|
|
4
|
-
createActor,
|
|
5
|
-
EventObject,
|
|
6
|
-
fromTransition,
|
|
7
|
-
Observer,
|
|
8
|
-
toObserver,
|
|
9
|
-
} from 'xstate';
|
|
10
|
-
import { ZodContextMapping, ZodEventMapping } from './schemas';
|
|
11
|
-
import {
|
|
12
|
-
Agent,
|
|
13
|
-
AgentLogic,
|
|
14
|
-
AgentMessage,
|
|
15
|
-
AgentPlanner,
|
|
16
|
-
EventsFromZodEventMapping,
|
|
17
|
-
GenerateTextOptions,
|
|
18
|
-
AgentLongTermMemory,
|
|
19
|
-
AIAdapter,
|
|
20
|
-
ObservedState,
|
|
21
|
-
AgentObservationInput,
|
|
22
|
-
AgentMemoryContext,
|
|
23
|
-
AgentObservation,
|
|
24
|
-
ContextFromZodContextMapping,
|
|
25
|
-
AgentFeedback,
|
|
26
|
-
} from './types';
|
|
27
|
-
import { simplePlanner } from './planners/simplePlanner';
|
|
28
|
-
import { agentGenerateText, agentStreamText } from './text';
|
|
29
|
-
import { agentDecide } from './decision';
|
|
30
|
-
import { vercelAdapter } from './adapters/vercel';
|
|
31
|
-
import { getMachineHash, randomId } from './utils';
|
|
32
|
-
|
|
33
|
-
export const agentLogic: AgentLogic<AnyEventObject> = fromTransition(
|
|
34
|
-
(state, event, { emit }) => {
|
|
35
|
-
switch (event.type) {
|
|
36
|
-
case 'agent.feedback': {
|
|
37
|
-
state.feedback.push(event.feedback);
|
|
38
|
-
emit({
|
|
39
|
-
type: 'feedback',
|
|
40
|
-
// @ts-ignore TODO: fix types in XState
|
|
41
|
-
feedback: event.feedback,
|
|
42
|
-
});
|
|
43
|
-
break;
|
|
44
|
-
}
|
|
45
|
-
case 'agent.observe': {
|
|
46
|
-
state.observations.push(event.observation);
|
|
47
|
-
emit({
|
|
48
|
-
type: 'observation',
|
|
49
|
-
// @ts-ignore TODO: fix types in XState
|
|
50
|
-
observation: event.observation,
|
|
51
|
-
});
|
|
52
|
-
break;
|
|
53
|
-
}
|
|
54
|
-
case 'agent.message': {
|
|
55
|
-
state.messages.push(event.message);
|
|
56
|
-
emit({
|
|
57
|
-
type: 'message',
|
|
58
|
-
// @ts-ignore TODO: fix types in XState
|
|
59
|
-
message: event.message,
|
|
60
|
-
});
|
|
61
|
-
break;
|
|
62
|
-
}
|
|
63
|
-
case 'agent.plan': {
|
|
64
|
-
state.plans.push(event.plan);
|
|
65
|
-
emit({
|
|
66
|
-
type: 'plan',
|
|
67
|
-
// @ts-ignore TODO: fix types in XState
|
|
68
|
-
plan: event.plan,
|
|
69
|
-
});
|
|
70
|
-
break;
|
|
71
|
-
}
|
|
72
|
-
default:
|
|
73
|
-
break;
|
|
74
|
-
}
|
|
75
|
-
return state;
|
|
76
|
-
},
|
|
77
|
-
() =>
|
|
78
|
-
({
|
|
79
|
-
feedback: [],
|
|
80
|
-
messages: [],
|
|
81
|
-
observations: [],
|
|
82
|
-
plans: [],
|
|
83
|
-
} as AgentMemoryContext)
|
|
84
|
-
);
|
|
85
|
-
|
|
86
|
-
export function createAgent<
|
|
87
|
-
const TContextSchema extends ZodContextMapping,
|
|
88
|
-
const TEventSchemas extends ZodEventMapping,
|
|
89
|
-
TEvents extends EventObject = EventsFromZodEventMapping<TEventSchemas>,
|
|
90
|
-
TContext = ContextFromZodContextMapping<TContextSchema>
|
|
91
|
-
>({
|
|
92
|
-
name,
|
|
93
|
-
description,
|
|
94
|
-
model,
|
|
95
|
-
events,
|
|
96
|
-
context,
|
|
97
|
-
planner = simplePlanner as AgentPlanner<Agent<TContext, TEvents>>,
|
|
98
|
-
stringify = JSON.stringify,
|
|
99
|
-
getMemory,
|
|
100
|
-
logic = agentLogic as AgentLogic<TEvents>,
|
|
101
|
-
adapter = vercelAdapter,
|
|
102
|
-
...generateTextOptions
|
|
103
|
-
}: {
|
|
104
|
-
/**
|
|
105
|
-
* The unique identifier for the agent.
|
|
106
|
-
*
|
|
107
|
-
* This should be the same across all sessions of a specific agent, as it can be
|
|
108
|
-
* used to retrieve memory for this agent.
|
|
109
|
-
*
|
|
110
|
-
* @example
|
|
111
|
-
* ```ts
|
|
112
|
-
* const agent = createAgent({
|
|
113
|
-
* id: 'recipe-assistant',
|
|
114
|
-
* // ...
|
|
115
|
-
* });
|
|
116
|
-
* ```
|
|
117
|
-
*/
|
|
118
|
-
id?: string;
|
|
119
|
-
/**
|
|
120
|
-
* The name of the agent
|
|
121
|
-
*/
|
|
122
|
-
name?: string;
|
|
123
|
-
/**
|
|
124
|
-
* A description of the role of the agent
|
|
125
|
-
*/
|
|
126
|
-
description?: string;
|
|
127
|
-
/**
|
|
128
|
-
* Events that the agent can cause (send) in an environment
|
|
129
|
-
* that the agent knows about.
|
|
130
|
-
*/
|
|
131
|
-
events: TEventSchemas;
|
|
132
|
-
context?: TContextSchema;
|
|
133
|
-
planner?: AgentPlanner<Agent<TContext, TEvents>>;
|
|
134
|
-
stringify?: typeof JSON.stringify;
|
|
135
|
-
/**
|
|
136
|
-
* A function that retrieves the agent's long term memory
|
|
137
|
-
*/
|
|
138
|
-
getMemory?: (agent: Agent<TContext, TEvents>) => AgentLongTermMemory;
|
|
139
|
-
/**
|
|
140
|
-
* Agent logic
|
|
141
|
-
*/
|
|
142
|
-
logic?: AgentLogic<TEvents>;
|
|
143
|
-
adapter?: AIAdapter;
|
|
144
|
-
} & GenerateTextOptions): Agent<TContext, TEvents> {
|
|
145
|
-
const agent = createActor(logic) as unknown as Agent<TContext, TEvents>;
|
|
146
|
-
agent.events = events;
|
|
147
|
-
agent.model = model;
|
|
148
|
-
agent.name = name;
|
|
149
|
-
agent.description = description;
|
|
150
|
-
agent.adapter = adapter;
|
|
151
|
-
agent.defaultOptions = { ...generateTextOptions, model };
|
|
152
|
-
agent.select = (selector) => {
|
|
153
|
-
return selector(agent.getSnapshot().context);
|
|
154
|
-
};
|
|
155
|
-
agent.memory = getMemory ? getMemory(agent) : undefined;
|
|
156
|
-
|
|
157
|
-
agent.onMessage = (callback) => {
|
|
158
|
-
agent.on('message', (ev) => callback(ev.message));
|
|
159
|
-
};
|
|
160
|
-
|
|
161
|
-
agent.decide = (opts) => {
|
|
162
|
-
return agentDecide(agent, opts);
|
|
163
|
-
};
|
|
164
|
-
|
|
165
|
-
agent.addMessage = (messageInput) => {
|
|
166
|
-
const message = {
|
|
167
|
-
...messageInput,
|
|
168
|
-
id: messageInput.id ?? randomId(),
|
|
169
|
-
timestamp: messageInput.timestamp ?? Date.now(),
|
|
170
|
-
sessionId: agent.sessionId,
|
|
171
|
-
correlationId: messageInput.correlationId ?? randomId(),
|
|
172
|
-
} satisfies AgentMessage;
|
|
173
|
-
agent.send({
|
|
174
|
-
type: 'agent.message',
|
|
175
|
-
message,
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
return message;
|
|
179
|
-
};
|
|
180
|
-
agent.getMessages = () => agent.getSnapshot().context.messages;
|
|
181
|
-
|
|
182
|
-
agent.generateText = (opts) => agentGenerateText(agent, opts);
|
|
183
|
-
|
|
184
|
-
agent.streamText = (opts) => agentStreamText(agent, opts);
|
|
185
|
-
|
|
186
|
-
agent.addFeedback = (feedbackInput) => {
|
|
187
|
-
const feedback = {
|
|
188
|
-
...feedbackInput,
|
|
189
|
-
attributes: { ...feedbackInput.attributes },
|
|
190
|
-
reward: feedbackInput.reward ?? 0,
|
|
191
|
-
timestamp: feedbackInput.timestamp ?? Date.now(),
|
|
192
|
-
sessionId: agent.sessionId,
|
|
193
|
-
} satisfies AgentFeedback;
|
|
194
|
-
agent.send({
|
|
195
|
-
type: 'agent.feedback',
|
|
196
|
-
feedback,
|
|
197
|
-
});
|
|
198
|
-
return feedback;
|
|
199
|
-
};
|
|
200
|
-
agent.getFeedback = () => agent.getSnapshot().context.feedback;
|
|
201
|
-
|
|
202
|
-
agent.addObservation = (observationInput) => {
|
|
203
|
-
const { prevState, event, state } = observationInput;
|
|
204
|
-
const observation = {
|
|
205
|
-
prevState,
|
|
206
|
-
event,
|
|
207
|
-
state,
|
|
208
|
-
id: observationInput.id ?? randomId(),
|
|
209
|
-
sessionId: agent.sessionId,
|
|
210
|
-
timestamp: observationInput.timestamp ?? Date.now(),
|
|
211
|
-
machineHash: observationInput.machine
|
|
212
|
-
? getMachineHash(observationInput.machine)
|
|
213
|
-
: undefined,
|
|
214
|
-
} satisfies AgentObservation<any>;
|
|
215
|
-
|
|
216
|
-
agent.send({
|
|
217
|
-
type: 'agent.observe',
|
|
218
|
-
observation,
|
|
219
|
-
});
|
|
220
|
-
|
|
221
|
-
return observation;
|
|
222
|
-
};
|
|
223
|
-
agent.getObservations = () => agent.getSnapshot().context.observations;
|
|
224
|
-
|
|
225
|
-
agent.addPlan = (plan) => {
|
|
226
|
-
agent.send({
|
|
227
|
-
type: 'agent.plan',
|
|
228
|
-
plan,
|
|
229
|
-
});
|
|
230
|
-
};
|
|
231
|
-
agent.getPlans = () => agent.getSnapshot().context.plans;
|
|
232
|
-
|
|
233
|
-
agent.interact = ((actorRef, getInput) => {
|
|
234
|
-
let prevState: ObservedState | undefined = undefined;
|
|
235
|
-
let subscribed = true;
|
|
236
|
-
|
|
237
|
-
async function handleObservation(observationInput: AgentObservationInput) {
|
|
238
|
-
const observation = agent.addObservation(observationInput);
|
|
239
|
-
|
|
240
|
-
const input = getInput?.(observation);
|
|
241
|
-
|
|
242
|
-
if (input) {
|
|
243
|
-
await agentDecide(agent, {
|
|
244
|
-
machine: actorRef.src as AnyStateMachine,
|
|
245
|
-
state: observation.state,
|
|
246
|
-
execute: async (event) => {
|
|
247
|
-
actorRef.send(event);
|
|
248
|
-
},
|
|
249
|
-
...input,
|
|
250
|
-
});
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
prevState = observationInput.state;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
// Inspect system, but only observe specified actor
|
|
257
|
-
actorRef.system.inspect({
|
|
258
|
-
next: async (inspEvent) => {
|
|
259
|
-
if (
|
|
260
|
-
!subscribed ||
|
|
261
|
-
inspEvent.actorRef !== actorRef ||
|
|
262
|
-
inspEvent.type !== '@xstate.snapshot'
|
|
263
|
-
) {
|
|
264
|
-
return;
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
const observationInput = {
|
|
268
|
-
event: inspEvent.event,
|
|
269
|
-
prevState,
|
|
270
|
-
state: inspEvent.snapshot as any,
|
|
271
|
-
machine: (actorRef as any).src,
|
|
272
|
-
} satisfies AgentObservationInput;
|
|
273
|
-
|
|
274
|
-
await handleObservation(observationInput);
|
|
275
|
-
},
|
|
276
|
-
});
|
|
277
|
-
|
|
278
|
-
// If actor already started, interact with current state
|
|
279
|
-
if ((actorRef as any)._processingStatus === 1) {
|
|
280
|
-
handleObservation({
|
|
281
|
-
prevState: undefined,
|
|
282
|
-
event: { type: '' }, // TODO: unknown events?
|
|
283
|
-
state: actorRef.getSnapshot(),
|
|
284
|
-
machine: (actorRef as any).src,
|
|
285
|
-
});
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
return {
|
|
289
|
-
unsubscribe: () => {
|
|
290
|
-
subscribed = false;
|
|
291
|
-
}, // TODO: make this actually unsubscribe
|
|
292
|
-
};
|
|
293
|
-
}) as typeof agent.interact;
|
|
294
|
-
|
|
295
|
-
agent.types = {} as any;
|
|
296
|
-
|
|
297
|
-
agent.start();
|
|
298
|
-
|
|
299
|
-
return agent;
|
|
300
|
-
}
|
package/src/decision.test.ts
DELETED
|
@@ -1,179 +0,0 @@
|
|
|
1
|
-
import { test, expect } from 'vitest';
|
|
2
|
-
import { createAgent, fromDecision, type AIAdapter } from './';
|
|
3
|
-
import { createActor, createMachine, waitFor } from 'xstate';
|
|
4
|
-
import { z } from 'zod';
|
|
5
|
-
import { GenerateTextResult } from 'ai';
|
|
6
|
-
|
|
7
|
-
const mockToolDecision: AIAdapter['generateText'] = async (arg) => {
|
|
8
|
-
const keys = Object.keys(arg.tools!);
|
|
9
|
-
|
|
10
|
-
if (keys.length > 1) {
|
|
11
|
-
throw new Error('Expected only 1 choice');
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
if (keys.length === 0) {
|
|
15
|
-
return {
|
|
16
|
-
toolResults: [],
|
|
17
|
-
} as any as GenerateTextResult<any>;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
return {
|
|
21
|
-
toolResults: [
|
|
22
|
-
{
|
|
23
|
-
result: {
|
|
24
|
-
type: keys[0],
|
|
25
|
-
},
|
|
26
|
-
},
|
|
27
|
-
],
|
|
28
|
-
} as any as GenerateTextResult<any>;
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
test('fromDecision() makes a decision', async () => {
|
|
32
|
-
const agent = createAgent({
|
|
33
|
-
name: 'test',
|
|
34
|
-
model: {} as any,
|
|
35
|
-
events: {
|
|
36
|
-
doFirst: z.object({}),
|
|
37
|
-
doSecond: z.object({}),
|
|
38
|
-
},
|
|
39
|
-
adapter: {
|
|
40
|
-
generateText: async (arg) => {
|
|
41
|
-
const keys = Object.keys(arg.tools!);
|
|
42
|
-
|
|
43
|
-
if (keys.length !== 1) {
|
|
44
|
-
throw new Error('Expected only 1 choice');
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
return {
|
|
48
|
-
toolResults: [
|
|
49
|
-
{
|
|
50
|
-
result: {
|
|
51
|
-
type: keys[0],
|
|
52
|
-
},
|
|
53
|
-
},
|
|
54
|
-
],
|
|
55
|
-
} as any as GenerateTextResult<any>;
|
|
56
|
-
},
|
|
57
|
-
streamText: {} as any,
|
|
58
|
-
},
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
const machine = createMachine({
|
|
62
|
-
initial: 'first',
|
|
63
|
-
states: {
|
|
64
|
-
first: {
|
|
65
|
-
invoke: {
|
|
66
|
-
src: fromDecision(agent),
|
|
67
|
-
},
|
|
68
|
-
on: {
|
|
69
|
-
doFirst: 'second',
|
|
70
|
-
},
|
|
71
|
-
},
|
|
72
|
-
second: {
|
|
73
|
-
invoke: {
|
|
74
|
-
src: fromDecision(agent),
|
|
75
|
-
},
|
|
76
|
-
on: {
|
|
77
|
-
doSecond: 'third',
|
|
78
|
-
},
|
|
79
|
-
},
|
|
80
|
-
third: {},
|
|
81
|
-
},
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
const actor = createActor(machine);
|
|
85
|
-
|
|
86
|
-
actor.start();
|
|
87
|
-
|
|
88
|
-
await waitFor(actor, (s) => s.matches('third'));
|
|
89
|
-
|
|
90
|
-
expect(actor.getSnapshot().value).toBe('third');
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
test('interacts with an actor', async () => {
|
|
94
|
-
const agent = createAgent({
|
|
95
|
-
name: 'test',
|
|
96
|
-
model: {} as any,
|
|
97
|
-
events: {
|
|
98
|
-
doFirst: z.object({}),
|
|
99
|
-
doSecond: z.object({}),
|
|
100
|
-
},
|
|
101
|
-
adapter: {
|
|
102
|
-
generateText: mockToolDecision,
|
|
103
|
-
streamText: {} as any,
|
|
104
|
-
},
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
const machine = createMachine({
|
|
108
|
-
initial: 'first',
|
|
109
|
-
states: {
|
|
110
|
-
first: {
|
|
111
|
-
on: {
|
|
112
|
-
doFirst: 'second',
|
|
113
|
-
},
|
|
114
|
-
},
|
|
115
|
-
second: {
|
|
116
|
-
on: {
|
|
117
|
-
doSecond: 'third',
|
|
118
|
-
},
|
|
119
|
-
},
|
|
120
|
-
third: {},
|
|
121
|
-
},
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
const actor = createActor(machine);
|
|
125
|
-
|
|
126
|
-
agent.interact(actor, () => ({
|
|
127
|
-
goal: 'Some goal',
|
|
128
|
-
}));
|
|
129
|
-
|
|
130
|
-
actor.start();
|
|
131
|
-
|
|
132
|
-
await waitFor(actor, (s) => s.matches('third'));
|
|
133
|
-
|
|
134
|
-
expect(actor.getSnapshot().value).toBe('third');
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
test('interacts with an actor (late interaction)', async () => {
|
|
138
|
-
const agent = createAgent({
|
|
139
|
-
name: 'test',
|
|
140
|
-
model: {} as any,
|
|
141
|
-
events: {
|
|
142
|
-
doFirst: z.object({}),
|
|
143
|
-
doSecond: z.object({}),
|
|
144
|
-
},
|
|
145
|
-
adapter: {
|
|
146
|
-
generateText: mockToolDecision,
|
|
147
|
-
streamText: {} as any,
|
|
148
|
-
},
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
const machine = createMachine({
|
|
152
|
-
initial: 'first',
|
|
153
|
-
states: {
|
|
154
|
-
first: {
|
|
155
|
-
on: {
|
|
156
|
-
doFirst: 'second',
|
|
157
|
-
},
|
|
158
|
-
},
|
|
159
|
-
second: {
|
|
160
|
-
on: {
|
|
161
|
-
doSecond: 'third',
|
|
162
|
-
},
|
|
163
|
-
},
|
|
164
|
-
third: {},
|
|
165
|
-
},
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
const actor = createActor(machine);
|
|
169
|
-
|
|
170
|
-
actor.start();
|
|
171
|
-
|
|
172
|
-
agent.interact(actor, () => ({
|
|
173
|
-
goal: 'Some goal',
|
|
174
|
-
}));
|
|
175
|
-
|
|
176
|
-
await waitFor(actor, (s) => s.matches('third'));
|
|
177
|
-
|
|
178
|
-
expect(actor.getSnapshot().value).toBe('third');
|
|
179
|
-
});
|
package/src/decision.ts
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import { AnyActor, AnyMachineSnapshot, fromPromise } from 'xstate';
|
|
2
|
-
import {
|
|
3
|
-
AnyAgent,
|
|
4
|
-
AgentDecideOptions,
|
|
5
|
-
AgentDecisionLogic,
|
|
6
|
-
AgentDecisionInput,
|
|
7
|
-
AgentPlanner,
|
|
8
|
-
AgentPlan,
|
|
9
|
-
} from './types';
|
|
10
|
-
import { simplePlanner } from './planners/simplePlanner';
|
|
11
|
-
|
|
12
|
-
export async function agentDecide<T extends AnyAgent>(
|
|
13
|
-
agent: T,
|
|
14
|
-
options: AgentDecideOptions
|
|
15
|
-
): Promise<AgentPlan<any> | undefined> {
|
|
16
|
-
const resolvedOptions = {
|
|
17
|
-
...agent.defaultOptions,
|
|
18
|
-
...options,
|
|
19
|
-
};
|
|
20
|
-
const {
|
|
21
|
-
planner = simplePlanner as AgentPlanner<any>,
|
|
22
|
-
goal,
|
|
23
|
-
events = agent.events,
|
|
24
|
-
state,
|
|
25
|
-
machine,
|
|
26
|
-
model = agent.model,
|
|
27
|
-
...otherPlanInput
|
|
28
|
-
} = resolvedOptions;
|
|
29
|
-
|
|
30
|
-
const plan = await planner(agent, {
|
|
31
|
-
model,
|
|
32
|
-
goal,
|
|
33
|
-
events,
|
|
34
|
-
state,
|
|
35
|
-
machine,
|
|
36
|
-
...otherPlanInput,
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
if (plan?.nextEvent) {
|
|
40
|
-
agent.addPlan(plan);
|
|
41
|
-
await resolvedOptions.execute?.(plan.nextEvent);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
return plan;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export function fromDecision(
|
|
48
|
-
agent: AnyAgent,
|
|
49
|
-
defaultInput?: AgentDecisionInput
|
|
50
|
-
): AgentDecisionLogic<any> {
|
|
51
|
-
return fromPromise(async ({ input, self }) => {
|
|
52
|
-
const parentRef = self._parent;
|
|
53
|
-
if (!parentRef) {
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const snapshot = parentRef.getSnapshot() as AnyMachineSnapshot;
|
|
58
|
-
const inputObject = typeof input === 'string' ? { goal: input } : input;
|
|
59
|
-
const resolvedInput = {
|
|
60
|
-
...defaultInput,
|
|
61
|
-
...inputObject,
|
|
62
|
-
};
|
|
63
|
-
const contextToInclude =
|
|
64
|
-
resolvedInput.context === true
|
|
65
|
-
? // include entire context
|
|
66
|
-
parentRef.getSnapshot().context
|
|
67
|
-
: resolvedInput.context;
|
|
68
|
-
const state = {
|
|
69
|
-
value: snapshot.value,
|
|
70
|
-
context: contextToInclude,
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
const plan = await agentDecide(agent, {
|
|
74
|
-
machine: (parentRef as AnyActor).logic,
|
|
75
|
-
state,
|
|
76
|
-
execute: async (event) => {
|
|
77
|
-
parentRef.send(event);
|
|
78
|
-
},
|
|
79
|
-
...resolvedInput,
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
return plan;
|
|
83
|
-
}) as AgentDecisionLogic<any>;
|
|
84
|
-
}
|
package/src/index.ts
DELETED
package/src/memory.ts
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { AgentMemory, AgentMemoryContext } from './types';
|
|
2
|
-
|
|
3
|
-
export function createAgentMemory(): AgentMemory {
|
|
4
|
-
const storage = {
|
|
5
|
-
sessions: {} as Record<string, AgentMemoryContext>,
|
|
6
|
-
};
|
|
7
|
-
|
|
8
|
-
return {
|
|
9
|
-
append: async (sessionId, key, item) => {
|
|
10
|
-
storage.sessions[sessionId] =
|
|
11
|
-
storage.sessions[sessionId] ||
|
|
12
|
-
({
|
|
13
|
-
observations: [],
|
|
14
|
-
messages: [],
|
|
15
|
-
plans: [],
|
|
16
|
-
feedback: [],
|
|
17
|
-
} satisfies AgentMemoryContext);
|
|
18
|
-
|
|
19
|
-
storage.sessions[sessionId]![key].push(item as any);
|
|
20
|
-
},
|
|
21
|
-
getAll: async (sessionId, key) => {
|
|
22
|
-
return storage.sessions[sessionId]?.[key];
|
|
23
|
-
},
|
|
24
|
-
};
|
|
25
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { Agent, AgentPlan, AgentPlanInput, AnyAgent } from '../types';
|
|
2
|
-
import { getShortestPaths } from '@xstate/graph';
|
|
3
|
-
|
|
4
|
-
export async function simplePlanner<T extends AnyAgent>(
|
|
5
|
-
agent: T,
|
|
6
|
-
input: AgentPlanInput<any>
|
|
7
|
-
): Promise<AgentPlan<any> | undefined> {
|
|
8
|
-
// 1. Determine goal state criteria
|
|
9
|
-
// e.g. a state where the agent has won a game
|
|
10
|
-
void 0;
|
|
11
|
-
|
|
12
|
-
// 2. Determine possible events that can occur
|
|
13
|
-
void 0;
|
|
14
|
-
|
|
15
|
-
// 3. Get shortest paths from current state to
|
|
16
|
-
// a state matching the criteria, using
|
|
17
|
-
// possible events
|
|
18
|
-
void 0;
|
|
19
|
-
|
|
20
|
-
// 4. Return shortest path as a plan
|
|
21
|
-
return null as any;
|
|
22
|
-
}
|