@statelyai/agent 0.1.1 → 0.1.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/shaggy-buttons-itch.md +5 -0
- package/dist/index.d.mts +303 -2
- package/dist/index.js +11 -3924
- package/dist/index.mjs +513 -4
- package/package.json +3 -2
- package/src/agent.ts +3 -3
- package/src/planners/simplePlanner.ts +5 -2
- package/src/schemas.ts +1 -1
- package/src/text.ts +4 -5
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,516 @@
|
|
|
1
|
-
// src/
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
// src/agent.ts
|
|
2
|
+
import {
|
|
3
|
+
createActor,
|
|
4
|
+
fromTransition,
|
|
5
|
+
toObserver as toObserver2
|
|
6
|
+
} from "xstate";
|
|
7
|
+
|
|
8
|
+
// src/planners/simplePlanner.ts
|
|
9
|
+
import { tool } from "ai";
|
|
10
|
+
|
|
11
|
+
// src/utils.ts
|
|
12
|
+
function getAllTransitions(state) {
|
|
13
|
+
const nodes = state._nodes;
|
|
14
|
+
const transitions = nodes.map((node) => [...node.transitions.values()]).flat(2).map((transition) => ({
|
|
15
|
+
...transition,
|
|
16
|
+
guard: typeof transition.guard === "string" ? { type: transition.guard } : transition.guard
|
|
17
|
+
// TODO: fix
|
|
18
|
+
}));
|
|
19
|
+
return transitions;
|
|
20
|
+
}
|
|
21
|
+
function wrapInXml(tagName, content) {
|
|
22
|
+
return `<${tagName}>${content}</${tagName}>`;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// src/templates/defaultText.ts
|
|
26
|
+
var defaultTextTemplate = (data) => {
|
|
27
|
+
const preamble = [
|
|
28
|
+
data.context ? wrapInXml("context", JSON.stringify(data.context)) : void 0
|
|
29
|
+
].filter(Boolean).join("\n");
|
|
30
|
+
return `
|
|
31
|
+
${preamble}
|
|
32
|
+
|
|
33
|
+
${data.goal}
|
|
34
|
+
`.trim();
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
// src/planners/simplePlanner.ts
|
|
38
|
+
function getTransitions(state, machine) {
|
|
39
|
+
if (!machine) {
|
|
40
|
+
return [];
|
|
41
|
+
}
|
|
42
|
+
const resolvedState = machine.resolveState(state);
|
|
43
|
+
return getAllTransitions(resolvedState);
|
|
44
|
+
}
|
|
45
|
+
var simplePlannerPromptTemplate = (data) => {
|
|
46
|
+
return `
|
|
47
|
+
${defaultTextTemplate(data)}
|
|
48
|
+
|
|
49
|
+
Only make a single tool call to achieve the above goal.
|
|
50
|
+
`.trim();
|
|
51
|
+
};
|
|
52
|
+
async function simplePlanner(agent, input) {
|
|
53
|
+
const transitions = input.machine ? getTransitions(input.state, input.machine) : Object.entries(input.events).map(([eventType, { description }]) => ({
|
|
54
|
+
eventType,
|
|
55
|
+
description
|
|
56
|
+
}));
|
|
57
|
+
const filter = (eventType) => Object.keys(input.events).includes(eventType);
|
|
58
|
+
const functionNameMapping = {};
|
|
59
|
+
const toolTransitions = transitions.filter((t) => {
|
|
60
|
+
return filter(t.eventType);
|
|
61
|
+
}).map((t) => {
|
|
62
|
+
const name = t.eventType.replace(/\./g, "_");
|
|
63
|
+
functionNameMapping[name] = t.eventType;
|
|
64
|
+
return {
|
|
65
|
+
type: "function",
|
|
66
|
+
eventType: t.eventType,
|
|
67
|
+
description: t.description,
|
|
68
|
+
name
|
|
69
|
+
};
|
|
70
|
+
});
|
|
71
|
+
const toolMap = {};
|
|
72
|
+
for (const toolTransitionData of toolTransitions) {
|
|
73
|
+
const toolZodType = input.events?.[toolTransitionData.eventType];
|
|
74
|
+
if (!toolZodType) {
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
toolMap[toolTransitionData.name] = tool({
|
|
78
|
+
description: toolZodType?.description ?? toolTransitionData.description,
|
|
79
|
+
parameters: toolZodType,
|
|
80
|
+
execute: async (params) => {
|
|
81
|
+
const event = {
|
|
82
|
+
type: toolTransitionData.eventType,
|
|
83
|
+
...params
|
|
84
|
+
};
|
|
85
|
+
return event;
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
const prompt = simplePlannerPromptTemplate({
|
|
90
|
+
context: input.state.context,
|
|
91
|
+
goal: input.goal
|
|
92
|
+
});
|
|
93
|
+
const result = await agent.generateText({
|
|
94
|
+
prompt,
|
|
95
|
+
tools: toolMap,
|
|
96
|
+
toolChoice: "required",
|
|
97
|
+
...input
|
|
98
|
+
});
|
|
99
|
+
const singleResult = result.toolResults[0];
|
|
100
|
+
if (!singleResult) {
|
|
101
|
+
console.warn("No tool call results returned");
|
|
102
|
+
return void 0;
|
|
103
|
+
}
|
|
104
|
+
return {
|
|
105
|
+
goal: input.goal,
|
|
106
|
+
state: input.state,
|
|
107
|
+
steps: [
|
|
108
|
+
{
|
|
109
|
+
event: singleResult.result
|
|
110
|
+
}
|
|
111
|
+
],
|
|
112
|
+
nextEvent: singleResult.result,
|
|
113
|
+
sessionId: agent.sessionId,
|
|
114
|
+
timestamp: Date.now()
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// src/text.ts
|
|
119
|
+
import {
|
|
120
|
+
fromObservable,
|
|
121
|
+
fromPromise,
|
|
122
|
+
toObserver
|
|
123
|
+
} from "xstate";
|
|
124
|
+
import { nanoid } from "nanoid";
|
|
125
|
+
async function getMessages(agent, prompt, options) {
|
|
126
|
+
let messages = [];
|
|
127
|
+
if (options.messages === true) {
|
|
128
|
+
messages = agent.select((s) => s.messages);
|
|
129
|
+
} else if (typeof options.messages === "function") {
|
|
130
|
+
messages = await options.messages(agent);
|
|
131
|
+
} else if (options.messages) {
|
|
132
|
+
messages = options.messages;
|
|
133
|
+
}
|
|
134
|
+
messages = messages.concat({
|
|
135
|
+
role: "user",
|
|
136
|
+
content: prompt
|
|
137
|
+
});
|
|
138
|
+
return messages;
|
|
139
|
+
}
|
|
140
|
+
async function agentGenerateText(agent, options) {
|
|
141
|
+
const resolvedOptions = {
|
|
142
|
+
...agent.defaultOptions,
|
|
143
|
+
...options
|
|
144
|
+
};
|
|
145
|
+
const template = resolvedOptions.template ?? defaultTextTemplate;
|
|
146
|
+
const id = nanoid();
|
|
147
|
+
const goal = typeof resolvedOptions.prompt === "string" ? resolvedOptions.prompt : await resolvedOptions.prompt(agent);
|
|
148
|
+
const promptWithContext = template({
|
|
149
|
+
goal,
|
|
150
|
+
context: resolvedOptions.context
|
|
151
|
+
});
|
|
152
|
+
const messages = await getMessages(agent, promptWithContext, resolvedOptions);
|
|
153
|
+
agent.addMessage({
|
|
154
|
+
id,
|
|
155
|
+
role: "user",
|
|
156
|
+
content: promptWithContext,
|
|
157
|
+
timestamp: Date.now()
|
|
158
|
+
});
|
|
159
|
+
const result = await agent.adapter.generateText({
|
|
160
|
+
...resolvedOptions,
|
|
161
|
+
prompt: void 0,
|
|
162
|
+
messages
|
|
163
|
+
});
|
|
164
|
+
agent.addMessage({
|
|
165
|
+
content: result.text,
|
|
166
|
+
id,
|
|
167
|
+
role: "assistant",
|
|
168
|
+
timestamp: Date.now(),
|
|
169
|
+
responseId: id,
|
|
170
|
+
result
|
|
171
|
+
});
|
|
172
|
+
return result;
|
|
173
|
+
}
|
|
174
|
+
async function agentStreamText(agent, options) {
|
|
175
|
+
const resolvedOptions = {
|
|
176
|
+
...agent.defaultOptions,
|
|
177
|
+
...options
|
|
178
|
+
};
|
|
179
|
+
const template = resolvedOptions.template ?? defaultTextTemplate;
|
|
180
|
+
const id = nanoid();
|
|
181
|
+
const goal = typeof resolvedOptions.prompt === "string" ? resolvedOptions.prompt : await resolvedOptions.prompt(agent);
|
|
182
|
+
const promptWithContext = template({
|
|
183
|
+
goal,
|
|
184
|
+
context: resolvedOptions.context
|
|
185
|
+
});
|
|
186
|
+
const messages = await getMessages(agent, promptWithContext, resolvedOptions);
|
|
187
|
+
agent.addMessage({
|
|
188
|
+
role: "user",
|
|
189
|
+
content: promptWithContext,
|
|
190
|
+
id,
|
|
191
|
+
timestamp: Date.now()
|
|
192
|
+
});
|
|
193
|
+
const result = await agent.adapter.streamText({
|
|
194
|
+
...resolvedOptions,
|
|
195
|
+
prompt: void 0,
|
|
196
|
+
messages,
|
|
197
|
+
onFinish: async (res) => {
|
|
198
|
+
agent.addMessage({
|
|
199
|
+
role: "assistant",
|
|
200
|
+
result: {
|
|
201
|
+
text: res.text,
|
|
202
|
+
finishReason: res.finishReason,
|
|
203
|
+
logprobs: void 0,
|
|
204
|
+
responseMessages: [],
|
|
205
|
+
toolCalls: [],
|
|
206
|
+
toolResults: [],
|
|
207
|
+
usage: res.usage,
|
|
208
|
+
warnings: res.warnings,
|
|
209
|
+
rawResponse: res.rawResponse
|
|
210
|
+
},
|
|
211
|
+
content: res.text,
|
|
212
|
+
id: nanoid(),
|
|
213
|
+
timestamp: Date.now(),
|
|
214
|
+
responseId: id
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
return result;
|
|
219
|
+
}
|
|
220
|
+
function fromTextStream(agent, defaultOptions) {
|
|
221
|
+
return fromObservable(({ input, self }) => {
|
|
222
|
+
const context = input.context === true ? (self._parent?.getSnapshot()).context : input.context;
|
|
223
|
+
const observers = /* @__PURE__ */ new Set();
|
|
224
|
+
(async () => {
|
|
225
|
+
const result = await agentStreamText(agent, {
|
|
226
|
+
...defaultOptions,
|
|
227
|
+
...input,
|
|
228
|
+
context
|
|
229
|
+
});
|
|
230
|
+
for await (const part of result.fullStream) {
|
|
231
|
+
if (part.type === "text-delta") {
|
|
232
|
+
observers.forEach((observer) => {
|
|
233
|
+
observer.next?.(part);
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
})();
|
|
238
|
+
return {
|
|
239
|
+
subscribe: (...args) => {
|
|
240
|
+
const observer = toObserver(...args);
|
|
241
|
+
observers.add(observer);
|
|
242
|
+
return {
|
|
243
|
+
unsubscribe: () => {
|
|
244
|
+
observers.delete(observer);
|
|
245
|
+
}
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
};
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
function fromText(agent, defaultOptions) {
|
|
252
|
+
return fromPromise(async ({ input, self }) => {
|
|
253
|
+
const context = input.context === true ? (self._parent?.getSnapshot()).context : input.context;
|
|
254
|
+
return await agentGenerateText(agent, {
|
|
255
|
+
...input,
|
|
256
|
+
...defaultOptions,
|
|
257
|
+
context
|
|
258
|
+
});
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// src/decision.ts
|
|
263
|
+
import { fromPromise as fromPromise2 } from "xstate";
|
|
264
|
+
async function agentDecide(agent, options) {
|
|
265
|
+
const resolvedOptions = {
|
|
266
|
+
...agent.defaultOptions,
|
|
267
|
+
...options
|
|
268
|
+
};
|
|
269
|
+
const {
|
|
270
|
+
planner = simplePlanner,
|
|
271
|
+
goal,
|
|
272
|
+
events = agent.events,
|
|
273
|
+
state,
|
|
274
|
+
machine,
|
|
275
|
+
model = agent.model,
|
|
276
|
+
...otherPlanInput
|
|
277
|
+
} = resolvedOptions;
|
|
278
|
+
const plan = await planner(agent, {
|
|
279
|
+
model,
|
|
280
|
+
goal,
|
|
281
|
+
events,
|
|
282
|
+
state,
|
|
283
|
+
machine,
|
|
284
|
+
...otherPlanInput
|
|
285
|
+
});
|
|
286
|
+
if (plan?.nextEvent) {
|
|
287
|
+
agent.addPlan(plan);
|
|
288
|
+
await resolvedOptions.execute?.(plan.nextEvent);
|
|
289
|
+
}
|
|
290
|
+
return plan;
|
|
291
|
+
}
|
|
292
|
+
function fromDecision(agent, defaultInput) {
|
|
293
|
+
return fromPromise2(async ({ input, self }) => {
|
|
294
|
+
const parentRef = self._parent;
|
|
295
|
+
if (!parentRef) {
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
const snapshot = parentRef.getSnapshot();
|
|
299
|
+
const inputObject = typeof input === "string" ? { goal: input } : input;
|
|
300
|
+
const resolvedInput = {
|
|
301
|
+
...defaultInput,
|
|
302
|
+
...inputObject
|
|
303
|
+
};
|
|
304
|
+
const contextToInclude = resolvedInput.context === true ? (
|
|
305
|
+
// include entire context
|
|
306
|
+
parentRef.getSnapshot().context
|
|
307
|
+
) : resolvedInput.context;
|
|
308
|
+
const state = {
|
|
309
|
+
value: snapshot.value,
|
|
310
|
+
context: contextToInclude
|
|
311
|
+
};
|
|
312
|
+
const plan = await agentDecide(agent, {
|
|
313
|
+
machine: parentRef.src,
|
|
314
|
+
state,
|
|
315
|
+
execute: async (event) => {
|
|
316
|
+
parentRef.send(event);
|
|
317
|
+
},
|
|
318
|
+
...resolvedInput
|
|
319
|
+
});
|
|
320
|
+
return plan;
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// src/adapters/vercel.ts
|
|
325
|
+
import { generateText, streamText } from "ai";
|
|
326
|
+
var vercelAdapter = {
|
|
327
|
+
generateText,
|
|
328
|
+
streamText
|
|
329
|
+
};
|
|
330
|
+
|
|
331
|
+
// src/agent.ts
|
|
332
|
+
import { nanoid as nanoid2 } from "nanoid";
|
|
333
|
+
var agentLogic = fromTransition(
|
|
334
|
+
(state, event, { emit }) => {
|
|
335
|
+
switch (event.type) {
|
|
336
|
+
case "agent.feedback": {
|
|
337
|
+
state.feedback.push(event.feedback);
|
|
338
|
+
emit({
|
|
339
|
+
type: "feedback",
|
|
340
|
+
// @ts-ignore TODO: fix types in XState
|
|
341
|
+
feedback: event.feedback
|
|
342
|
+
});
|
|
343
|
+
break;
|
|
344
|
+
}
|
|
345
|
+
case "agent.observe": {
|
|
346
|
+
state.observations.push(event.observation);
|
|
347
|
+
emit({
|
|
348
|
+
type: "observation",
|
|
349
|
+
// @ts-ignore TODO: fix types in XState
|
|
350
|
+
observation: event.observation
|
|
351
|
+
});
|
|
352
|
+
break;
|
|
353
|
+
}
|
|
354
|
+
case "agent.message": {
|
|
355
|
+
state.messages.push(event.message);
|
|
356
|
+
emit({
|
|
357
|
+
type: "message",
|
|
358
|
+
// @ts-ignore TODO: fix types in XState
|
|
359
|
+
message: event.message
|
|
360
|
+
});
|
|
361
|
+
break;
|
|
362
|
+
}
|
|
363
|
+
case "agent.plan": {
|
|
364
|
+
state.plans.push(event.plan);
|
|
365
|
+
emit({
|
|
366
|
+
type: "plan",
|
|
367
|
+
// @ts-ignore TODO: fix types in XState
|
|
368
|
+
plan: event.plan
|
|
369
|
+
});
|
|
370
|
+
break;
|
|
371
|
+
}
|
|
372
|
+
default:
|
|
373
|
+
break;
|
|
374
|
+
}
|
|
375
|
+
return state;
|
|
376
|
+
},
|
|
377
|
+
{
|
|
378
|
+
feedback: [],
|
|
379
|
+
messages: [],
|
|
380
|
+
observations: [],
|
|
381
|
+
plans: []
|
|
382
|
+
}
|
|
383
|
+
);
|
|
384
|
+
function createAgent({
|
|
385
|
+
name,
|
|
386
|
+
description,
|
|
387
|
+
model,
|
|
388
|
+
events,
|
|
389
|
+
planner = simplePlanner,
|
|
390
|
+
stringify = JSON.stringify,
|
|
391
|
+
getMemory,
|
|
392
|
+
logic = agentLogic,
|
|
393
|
+
adapter = vercelAdapter,
|
|
394
|
+
...generateTextOptions
|
|
395
|
+
}) {
|
|
396
|
+
const messageHistoryListeners = [];
|
|
397
|
+
const agent = createActor(logic);
|
|
398
|
+
agent.events = events;
|
|
399
|
+
agent.model = model;
|
|
400
|
+
agent.name = name;
|
|
401
|
+
agent.description = description;
|
|
402
|
+
agent.adapter = adapter;
|
|
403
|
+
agent.defaultOptions = { ...generateTextOptions, model };
|
|
404
|
+
agent.select = (selector) => {
|
|
405
|
+
return selector(agent.getSnapshot().context);
|
|
406
|
+
};
|
|
407
|
+
agent.memory = getMemory ? getMemory(agent) : void 0;
|
|
408
|
+
agent.onMessage = (callback) => {
|
|
409
|
+
messageHistoryListeners.push(toObserver2(callback));
|
|
410
|
+
};
|
|
411
|
+
agent.decide = (opts) => {
|
|
412
|
+
return agentDecide(agent, opts);
|
|
413
|
+
};
|
|
414
|
+
agent.addMessage = (messageInput) => {
|
|
415
|
+
const message = {
|
|
416
|
+
...messageInput,
|
|
417
|
+
id: messageInput.id ?? nanoid2(),
|
|
418
|
+
timestamp: messageInput.timestamp ?? Date.now(),
|
|
419
|
+
sessionId: agent.sessionId
|
|
420
|
+
};
|
|
421
|
+
agent.send({
|
|
422
|
+
type: "agent.message",
|
|
423
|
+
message
|
|
424
|
+
});
|
|
425
|
+
return message;
|
|
426
|
+
};
|
|
427
|
+
agent.generateText = (opts) => agentGenerateText(agent, opts);
|
|
428
|
+
agent.streamText = (opts) => agentStreamText(agent, opts);
|
|
429
|
+
agent.addFeedback = (feedbackInput) => {
|
|
430
|
+
const feedback = {
|
|
431
|
+
...feedbackInput,
|
|
432
|
+
timestamp: feedbackInput.timestamp ?? Date.now(),
|
|
433
|
+
sessionId: agent.sessionId
|
|
434
|
+
};
|
|
435
|
+
agent.send({
|
|
436
|
+
type: "agent.feedback",
|
|
437
|
+
feedback
|
|
438
|
+
});
|
|
439
|
+
return feedback;
|
|
440
|
+
};
|
|
441
|
+
agent.addObservation = (observationInput) => {
|
|
442
|
+
const observation = {
|
|
443
|
+
...observationInput,
|
|
444
|
+
id: observationInput.id ?? nanoid2(),
|
|
445
|
+
sessionId: agent.sessionId,
|
|
446
|
+
timestamp: observationInput.timestamp ?? Date.now()
|
|
447
|
+
};
|
|
448
|
+
agent.send({
|
|
449
|
+
type: "agent.observe",
|
|
450
|
+
observation
|
|
451
|
+
});
|
|
452
|
+
return observation;
|
|
453
|
+
};
|
|
454
|
+
agent.addPlan = (plan) => {
|
|
455
|
+
agent.send({
|
|
456
|
+
type: "agent.plan",
|
|
457
|
+
plan
|
|
458
|
+
});
|
|
459
|
+
};
|
|
460
|
+
agent.interact = (actorRef, getInput) => {
|
|
461
|
+
let prevState = void 0;
|
|
462
|
+
let subscribed = true;
|
|
463
|
+
async function handleObservation(observationInput) {
|
|
464
|
+
const observation = agent.addObservation(observationInput);
|
|
465
|
+
const input = getInput?.(observation);
|
|
466
|
+
if (input) {
|
|
467
|
+
await agentDecide(agent, {
|
|
468
|
+
machine: actorRef.src,
|
|
469
|
+
state: observation.state,
|
|
470
|
+
execute: async (event) => {
|
|
471
|
+
actorRef.send(event);
|
|
472
|
+
},
|
|
473
|
+
...input
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
prevState = observationInput.state;
|
|
477
|
+
}
|
|
478
|
+
actorRef.system.inspect({
|
|
479
|
+
next: async (inspEvent) => {
|
|
480
|
+
if (!subscribed || inspEvent.actorRef !== actorRef || inspEvent.type !== "@xstate.snapshot") {
|
|
481
|
+
return;
|
|
482
|
+
}
|
|
483
|
+
const observationInput = {
|
|
484
|
+
event: inspEvent.event,
|
|
485
|
+
prevState,
|
|
486
|
+
state: inspEvent.snapshot
|
|
487
|
+
};
|
|
488
|
+
await handleObservation(observationInput);
|
|
489
|
+
}
|
|
490
|
+
});
|
|
491
|
+
if (actorRef._processingStatus === 1) {
|
|
492
|
+
handleObservation({
|
|
493
|
+
prevState: void 0,
|
|
494
|
+
event: { type: "" },
|
|
495
|
+
// TODO: unknown events?
|
|
496
|
+
state: actorRef.getSnapshot()
|
|
497
|
+
});
|
|
498
|
+
}
|
|
499
|
+
return {
|
|
500
|
+
unsubscribe: () => {
|
|
501
|
+
subscribed = false;
|
|
502
|
+
}
|
|
503
|
+
// TODO: make this actually unsubscribe
|
|
504
|
+
};
|
|
505
|
+
};
|
|
506
|
+
agent.start();
|
|
507
|
+
return agent;
|
|
4
508
|
}
|
|
5
509
|
export {
|
|
6
|
-
|
|
510
|
+
agentDecide,
|
|
511
|
+
agentGenerateText,
|
|
512
|
+
createAgent,
|
|
513
|
+
fromDecision,
|
|
514
|
+
fromText,
|
|
515
|
+
fromTextStream
|
|
7
516
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@statelyai/agent",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"lint": "tsc --noEmit",
|
|
11
11
|
"test": "vitest",
|
|
12
12
|
"example": "ts-node examples/helpers/runner.ts",
|
|
13
|
-
"prepublishOnly": "tsup src/index.ts --dts",
|
|
13
|
+
"prepublishOnly": "tsup src/index.ts --format cjs,esm --dts",
|
|
14
14
|
"changeset": "changeset",
|
|
15
15
|
"release": "changeset publish",
|
|
16
16
|
"version": "changeset version"
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
"@ai-sdk/openai": "^0.0.13",
|
|
42
42
|
"@xstate/graph": "^2.0.0",
|
|
43
43
|
"ai": "^3.1.32",
|
|
44
|
+
"nanoid": "^5.0.7",
|
|
44
45
|
"xstate": "^5.13.2"
|
|
45
46
|
},
|
|
46
47
|
"packageManager": "pnpm@8.11.0"
|
package/src/agent.ts
CHANGED
|
@@ -22,10 +22,10 @@ import {
|
|
|
22
22
|
AgentMemoryContext,
|
|
23
23
|
} from './types';
|
|
24
24
|
import { simplePlanner } from './planners/simplePlanner';
|
|
25
|
-
import { randomUUID } from 'crypto';
|
|
26
25
|
import { agentGenerateText, agentStreamText } from './text';
|
|
27
26
|
import { agentDecide } from './decision';
|
|
28
27
|
import { vercelAdapter } from './adapters/vercel';
|
|
28
|
+
import { nanoid } from 'nanoid';
|
|
29
29
|
|
|
30
30
|
export const agentLogic: AgentLogic<AnyEventObject> = fromTransition(
|
|
31
31
|
(state, event, { emit }) => {
|
|
@@ -144,7 +144,7 @@ export function createAgent<
|
|
|
144
144
|
agent.addMessage = (messageInput) => {
|
|
145
145
|
const message = {
|
|
146
146
|
...messageInput,
|
|
147
|
-
id: messageInput.id ??
|
|
147
|
+
id: messageInput.id ?? nanoid(),
|
|
148
148
|
timestamp: messageInput.timestamp ?? Date.now(),
|
|
149
149
|
sessionId: agent.sessionId,
|
|
150
150
|
};
|
|
@@ -176,7 +176,7 @@ export function createAgent<
|
|
|
176
176
|
agent.addObservation = (observationInput) => {
|
|
177
177
|
const observation = {
|
|
178
178
|
...observationInput,
|
|
179
|
-
id: observationInput.id ??
|
|
179
|
+
id: observationInput.id ?? nanoid(),
|
|
180
180
|
sessionId: agent.sessionId,
|
|
181
181
|
timestamp: observationInput.timestamp ?? Date.now(),
|
|
182
182
|
};
|
|
@@ -9,7 +9,6 @@ import {
|
|
|
9
9
|
} from '../types';
|
|
10
10
|
import { getAllTransitions } from '../utils';
|
|
11
11
|
import { AnyStateMachine } from 'xstate';
|
|
12
|
-
import { z } from 'zod';
|
|
13
12
|
import { defaultTextTemplate } from '../templates/defaultText';
|
|
14
13
|
|
|
15
14
|
function getTransitions(
|
|
@@ -75,9 +74,13 @@ export async function simplePlanner<T extends Agent<any>>(
|
|
|
75
74
|
for (const toolTransitionData of toolTransitions) {
|
|
76
75
|
const toolZodType = input.events?.[toolTransitionData.eventType];
|
|
77
76
|
|
|
77
|
+
if (!toolZodType) {
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
|
|
78
81
|
toolMap[toolTransitionData.name] = tool({
|
|
79
82
|
description: toolZodType?.description ?? toolTransitionData.description,
|
|
80
|
-
parameters: toolZodType
|
|
83
|
+
parameters: toolZodType,
|
|
81
84
|
execute: async (params) => {
|
|
82
85
|
const event = {
|
|
83
86
|
type: toolTransitionData.eventType,
|
package/src/schemas.ts
CHANGED
package/src/text.ts
CHANGED
|
@@ -9,7 +9,6 @@ import {
|
|
|
9
9
|
AgentGenerateTextOptions,
|
|
10
10
|
AgentStreamTextOptions,
|
|
11
11
|
} from './types';
|
|
12
|
-
import { randomUUID } from 'crypto';
|
|
13
12
|
import { defaultTextTemplate } from './templates/defaultText';
|
|
14
13
|
import {
|
|
15
14
|
AnyMachineSnapshot,
|
|
@@ -20,7 +19,7 @@ import {
|
|
|
20
19
|
fromPromise,
|
|
21
20
|
toObserver,
|
|
22
21
|
} from 'xstate';
|
|
23
|
-
import {
|
|
22
|
+
import { nanoid } from 'nanoid';
|
|
24
23
|
|
|
25
24
|
/**
|
|
26
25
|
* Gets an array of messages from the given prompt, based on the agent and options.
|
|
@@ -62,7 +61,7 @@ export async function agentGenerateText<T extends Agent<any>>(
|
|
|
62
61
|
};
|
|
63
62
|
const template = resolvedOptions.template ?? defaultTextTemplate;
|
|
64
63
|
// TODO: check if messages was provided instead
|
|
65
|
-
const id =
|
|
64
|
+
const id = nanoid();
|
|
66
65
|
const goal =
|
|
67
66
|
typeof resolvedOptions.prompt === 'string'
|
|
68
67
|
? resolvedOptions.prompt
|
|
@@ -110,7 +109,7 @@ export async function agentStreamText(
|
|
|
110
109
|
};
|
|
111
110
|
const template = resolvedOptions.template ?? defaultTextTemplate;
|
|
112
111
|
|
|
113
|
-
const id =
|
|
112
|
+
const id = nanoid();
|
|
114
113
|
const goal =
|
|
115
114
|
typeof resolvedOptions.prompt === 'string'
|
|
116
115
|
? resolvedOptions.prompt
|
|
@@ -149,7 +148,7 @@ export async function agentStreamText(
|
|
|
149
148
|
rawResponse: res.rawResponse,
|
|
150
149
|
},
|
|
151
150
|
content: res.text,
|
|
152
|
-
id:
|
|
151
|
+
id: nanoid(),
|
|
153
152
|
timestamp: Date.now(),
|
|
154
153
|
responseId: id,
|
|
155
154
|
});
|