@statelyai/agent 1.1.6 → 2.0.0-alpha.6

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.
Files changed (84) hide show
  1. package/LICENSE +21 -0
  2. package/dist/ai-sdk.cjs +249 -0
  3. package/dist/ai-sdk.d.cts +168 -0
  4. package/dist/ai-sdk.d.mts +168 -0
  5. package/dist/ai-sdk.mjs +241 -0
  6. package/dist/cli.cjs +63 -0
  7. package/dist/cli.d.cts +1 -0
  8. package/dist/cli.d.mts +1 -0
  9. package/dist/cli.mjs +64 -0
  10. package/dist/decision-CX3YdwrO.cjs +1239 -0
  11. package/dist/decision-D1654JdD.mjs +940 -0
  12. package/dist/index.cjs +54 -0
  13. package/dist/index.d.cts +1217 -0
  14. package/dist/index.d.mts +1194 -405
  15. package/dist/index.mjs +3 -588
  16. package/dist/openai-compat.cjs +319 -0
  17. package/dist/openai-compat.d.cts +98 -0
  18. package/dist/openai-compat.d.mts +98 -0
  19. package/dist/openai-compat.mjs +312 -0
  20. package/dist/src-CEa947Dm.mjs +2449 -0
  21. package/dist/src-wBfi-kTA.cjs +2568 -0
  22. package/dist/text-logic-1ZQkO3zr.d.cts +682 -0
  23. package/dist/text-logic-2EMJIS-n.d.mts +682 -0
  24. package/dist/types-BHjeDdch.d.cts +208 -0
  25. package/dist/types-Cq1YlAQ6.d.mts +208 -0
  26. package/dist/utils-CWUCa3pF.d.mts +108 -0
  27. package/dist/utils-lK1wnL2i.d.cts +108 -0
  28. package/dist/zod.cjs +31 -0
  29. package/dist/zod.d.cts +30 -0
  30. package/dist/zod.d.mts +30 -0
  31. package/dist/zod.mjs +30 -0
  32. package/package.json +109 -28
  33. package/readme.md +144 -6
  34. package/schemas/agent-workflow.json +527 -0
  35. package/.changeset/README.md +0 -8
  36. package/.changeset/config.json +0 -11
  37. package/.env.template +0 -3
  38. package/.github/actions/ci-setup/action.yml +0 -24
  39. package/.github/workflows/release.yml +0 -46
  40. package/.vscode/launch.json +0 -28
  41. package/CHANGELOG.md +0 -222
  42. package/dist/index.d.ts +0 -428
  43. package/dist/index.js +0 -621
  44. package/examples/chatbot.ts +0 -71
  45. package/examples/cot.ts +0 -89
  46. package/examples/email.ts +0 -118
  47. package/examples/example.ts +0 -81
  48. package/examples/goal.ts +0 -94
  49. package/examples/helpers/helpers.ts +0 -17
  50. package/examples/helpers/loader.ts +0 -32
  51. package/examples/helpers/runner.ts +0 -27
  52. package/examples/joke.ts +0 -225
  53. package/examples/multi.ts +0 -103
  54. package/examples/newspaper.ts +0 -324
  55. package/examples/number.ts +0 -102
  56. package/examples/raffle.ts +0 -105
  57. package/examples/sandbox.ts +0 -28
  58. package/examples/simple.ts +0 -39
  59. package/examples/support.ts +0 -147
  60. package/examples/ticTacToe.ts +0 -224
  61. package/examples/todo.ts +0 -137
  62. package/examples/tutor.ts +0 -100
  63. package/examples/verify.ts +0 -120
  64. package/examples/weather.ts +0 -178
  65. package/examples/wiki.ts +0 -30
  66. package/examples/word.ts +0 -171
  67. package/src/adapters/vercel.ts +0 -7
  68. package/src/agent-experimental.ts +0 -221
  69. package/src/agent.test.ts +0 -506
  70. package/src/agent.ts +0 -300
  71. package/src/decision.test.ts +0 -179
  72. package/src/decision.ts +0 -84
  73. package/src/index.ts +0 -4
  74. package/src/memory.ts +0 -25
  75. package/src/planners/shortestPathPlanner.ts +0 -22
  76. package/src/planners/simplePlanner.ts +0 -139
  77. package/src/schemas.ts +0 -11
  78. package/src/strategies/chain-of-note.ts +0 -155
  79. package/src/templates/defaultText.ts +0 -18
  80. package/src/text.ts +0 -241
  81. package/src/types.ts +0 -499
  82. package/src/utils.ts +0 -72
  83. package/tsconfig.json +0 -109
  84. 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
- }
@@ -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
@@ -1,4 +0,0 @@
1
- export { createAgent } from './agent';
2
- export { fromText, fromTextStream } from './text';
3
- export { fromDecision } from './decision';
4
- export * from './types';
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
- }