@statelyai/agent 1.1.6 → 2.0.0-next.0
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/light-hats-drive.md +9 -0
- package/.changeset/pre.json +10 -0
- package/.vscode/launch.json +6 -0
- package/CHANGELOG.md +10 -0
- package/dist/index.d.mts +262 -165
- package/dist/index.d.ts +262 -165
- package/dist/index.js +368 -263
- package/dist/index.mjs +371 -261
- package/examples/chatbot-alt.ts +57 -0
- package/examples/chatbot.ts +11 -16
- package/examples/cot.ts +25 -22
- package/examples/customer-service-sim.ts +107 -0
- package/examples/email.ts +14 -14
- package/examples/example.ts +5 -5
- package/examples/executor.ts +66 -0
- package/examples/goal.ts +11 -11
- package/examples/helpers/helpers.ts +26 -14
- package/examples/joke.ts +78 -75
- package/examples/jugs.ts +125 -0
- package/examples/multi.ts +4 -4
- package/examples/newspaper.ts +98 -104
- package/examples/number.ts +5 -4
- package/examples/raffle.ts +10 -11
- package/examples/river-crossing.ts +140 -0
- package/examples/sandbox.ts +1 -1
- package/examples/simple.ts +4 -2
- package/examples/summary.ts +121 -0
- package/examples/support.ts +5 -5
- package/examples/ticTacToe.ts +86 -45
- package/examples/todo.ts +6 -6
- package/examples/tutor.ts +13 -13
- package/examples/verify.ts +2 -2
- package/examples/weather.ts +5 -8
- package/examples/wiki.ts +26 -7
- package/examples/word.ts +15 -10
- package/package.json +13 -10
- package/readme.md +1 -1
- package/src/agent-experimental.ts +1 -1
- package/src/agent.test.ts +117 -228
- package/src/agent.ts +469 -81
- package/src/{decision.test.ts → decide.test.ts} +26 -50
- package/src/decide.ts +153 -0
- package/src/index.ts +1 -1
- package/src/middleware.ts +103 -0
- package/src/mockModel.ts +47 -0
- package/src/planners/shortestPathPlanner.ts +151 -13
- package/src/planners/simplePlanner.ts +57 -85
- package/src/strategies/chain-of-note.ts +6 -55
- package/src/text.ts +51 -144
- package/src/types.ts +172 -204
- package/src/utils.ts +37 -4
- package/src/adapters/vercel.ts +0 -7
- package/src/decision.ts +0 -84
- package/src/memory.ts +0 -25
package/dist/index.js
CHANGED
|
@@ -38,10 +38,10 @@ __export(src_exports, {
|
|
|
38
38
|
module.exports = __toCommonJS(src_exports);
|
|
39
39
|
|
|
40
40
|
// src/agent.ts
|
|
41
|
-
var
|
|
41
|
+
var import_xstate4 = require("xstate");
|
|
42
42
|
|
|
43
43
|
// src/planners/simplePlanner.ts
|
|
44
|
-
var
|
|
44
|
+
var import_ai3 = require("ai");
|
|
45
45
|
|
|
46
46
|
// src/utils.ts
|
|
47
47
|
var import_object_hash = __toESM(require("object-hash"));
|
|
@@ -79,10 +79,10 @@ function getAllMachineTransitions(stateNode) {
|
|
|
79
79
|
function wrapInXml(tagName, content) {
|
|
80
80
|
return `<${tagName}>${content}</${tagName}>`;
|
|
81
81
|
}
|
|
82
|
-
function randomId() {
|
|
82
|
+
function randomId(prefix) {
|
|
83
83
|
const timestamp = Date.now().toString(36);
|
|
84
84
|
const random = Math.random().toString(36).substring(2, 9);
|
|
85
|
-
return
|
|
85
|
+
return `${prefix || ""}${timestamp}${random}`;
|
|
86
86
|
}
|
|
87
87
|
var machineHashes = /* @__PURE__ */ new WeakMap();
|
|
88
88
|
function getMachineHash(machine) {
|
|
@@ -92,6 +92,23 @@ function getMachineHash(machine) {
|
|
|
92
92
|
machineHashes.set(machine, machineHash);
|
|
93
93
|
return machineHash;
|
|
94
94
|
}
|
|
95
|
+
function isActorRef(actorRefLike) {
|
|
96
|
+
return "src" in actorRefLike && "system" in actorRefLike && "sessionId" in actorRefLike;
|
|
97
|
+
}
|
|
98
|
+
function getTransitions(state, machine) {
|
|
99
|
+
if (!machine) {
|
|
100
|
+
return [];
|
|
101
|
+
}
|
|
102
|
+
const resolvedState = machine.resolveState({
|
|
103
|
+
...state,
|
|
104
|
+
// Need this property defined to make TS happy
|
|
105
|
+
context: state.context
|
|
106
|
+
});
|
|
107
|
+
return getAllTransitions(resolvedState);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// src/planners/simplePlanner.ts
|
|
111
|
+
var import_xstate3 = require("xstate");
|
|
95
112
|
|
|
96
113
|
// src/templates/defaultText.ts
|
|
97
114
|
var defaultTextTemplate = (data) => {
|
|
@@ -106,6 +123,7 @@ ${data.goal}
|
|
|
106
123
|
};
|
|
107
124
|
|
|
108
125
|
// src/text.ts
|
|
126
|
+
var import_ai = require("ai");
|
|
109
127
|
var import_xstate = require("xstate");
|
|
110
128
|
async function getMessages(agent, prompt, options) {
|
|
111
129
|
let messages = [];
|
|
@@ -120,120 +138,26 @@ async function getMessages(agent, prompt, options) {
|
|
|
120
138
|
});
|
|
121
139
|
return messages;
|
|
122
140
|
}
|
|
123
|
-
|
|
124
|
-
const
|
|
125
|
-
...agent.defaultOptions,
|
|
126
|
-
...options,
|
|
127
|
-
correlationId: options.correlationId ?? randomId()
|
|
128
|
-
};
|
|
129
|
-
const template = resolvedOptions.template ?? defaultTextTemplate;
|
|
130
|
-
const id = randomId();
|
|
131
|
-
const goal = typeof resolvedOptions.prompt === "string" ? resolvedOptions.prompt : await resolvedOptions.prompt(agent);
|
|
132
|
-
const promptWithContext = template({
|
|
133
|
-
goal,
|
|
134
|
-
context: resolvedOptions.context
|
|
135
|
-
});
|
|
136
|
-
const messages = await getMessages(agent, promptWithContext, resolvedOptions);
|
|
137
|
-
agent.addMessage({
|
|
138
|
-
id,
|
|
139
|
-
role: "user",
|
|
140
|
-
content: promptWithContext,
|
|
141
|
-
timestamp: Date.now(),
|
|
142
|
-
correlationId: resolvedOptions.correlationId,
|
|
143
|
-
parentCorrelationId: resolvedOptions.parentCorrelationId
|
|
144
|
-
});
|
|
145
|
-
const result = await agent.adapter.generateText({
|
|
146
|
-
...resolvedOptions,
|
|
147
|
-
prompt: void 0,
|
|
148
|
-
messages
|
|
149
|
-
});
|
|
150
|
-
agent.addMessage({
|
|
151
|
-
content: result.text,
|
|
152
|
-
id,
|
|
153
|
-
role: "assistant",
|
|
154
|
-
timestamp: Date.now(),
|
|
155
|
-
responseId: id,
|
|
156
|
-
result,
|
|
157
|
-
correlationId: resolvedOptions.correlationId,
|
|
158
|
-
parentCorrelationId: resolvedOptions.parentCorrelationId
|
|
159
|
-
});
|
|
160
|
-
return {
|
|
161
|
-
...result,
|
|
162
|
-
parentCorrelationId: resolvedOptions.parentCorrelationId,
|
|
163
|
-
correlationId: resolvedOptions.correlationId
|
|
164
|
-
};
|
|
165
|
-
}
|
|
166
|
-
async function agentStreamText(agent, options) {
|
|
167
|
-
const resolvedOptions = {
|
|
168
|
-
...agent.defaultOptions,
|
|
169
|
-
...options,
|
|
170
|
-
correlationId: options.correlationId ?? randomId()
|
|
171
|
-
};
|
|
172
|
-
const template = resolvedOptions.template ?? defaultTextTemplate;
|
|
173
|
-
const id = randomId();
|
|
174
|
-
const goal = typeof resolvedOptions.prompt === "string" ? resolvedOptions.prompt : await resolvedOptions.prompt(agent);
|
|
175
|
-
const promptWithContext = template({
|
|
176
|
-
goal,
|
|
177
|
-
context: resolvedOptions.context
|
|
178
|
-
});
|
|
179
|
-
const messages = await getMessages(agent, promptWithContext, resolvedOptions);
|
|
180
|
-
agent.addMessage({
|
|
181
|
-
role: "user",
|
|
182
|
-
content: promptWithContext,
|
|
183
|
-
id,
|
|
184
|
-
timestamp: Date.now(),
|
|
185
|
-
correlationId: resolvedOptions.correlationId,
|
|
186
|
-
parentCorrelationId: resolvedOptions.parentCorrelationId
|
|
187
|
-
});
|
|
188
|
-
const result = await agent.adapter.streamText({
|
|
189
|
-
...resolvedOptions,
|
|
190
|
-
prompt: void 0,
|
|
191
|
-
messages,
|
|
192
|
-
onFinish: async (res) => {
|
|
193
|
-
agent.addMessage({
|
|
194
|
-
role: "assistant",
|
|
195
|
-
result: {
|
|
196
|
-
text: res.text,
|
|
197
|
-
finishReason: res.finishReason,
|
|
198
|
-
logprobs: void 0,
|
|
199
|
-
responseMessages: [],
|
|
200
|
-
toolCalls: [],
|
|
201
|
-
toolResults: [],
|
|
202
|
-
usage: res.usage,
|
|
203
|
-
warnings: res.warnings,
|
|
204
|
-
rawResponse: res.rawResponse,
|
|
205
|
-
roundtrips: [],
|
|
206
|
-
// TODO: how do we get this information?,
|
|
207
|
-
steps: res.steps,
|
|
208
|
-
response: res.response,
|
|
209
|
-
experimental_providerMetadata: res.experimental_providerMetadata
|
|
210
|
-
},
|
|
211
|
-
content: res.text,
|
|
212
|
-
id: randomId(),
|
|
213
|
-
timestamp: Date.now(),
|
|
214
|
-
responseId: id,
|
|
215
|
-
correlationId: resolvedOptions.correlationId,
|
|
216
|
-
parentCorrelationId: resolvedOptions.parentCorrelationId
|
|
217
|
-
});
|
|
218
|
-
}
|
|
219
|
-
});
|
|
220
|
-
return {
|
|
221
|
-
...result,
|
|
222
|
-
textStream: result.textStream,
|
|
223
|
-
fullStream: result.fullStream,
|
|
224
|
-
parentCorrelationId: resolvedOptions.parentCorrelationId,
|
|
225
|
-
correlationId: resolvedOptions.correlationId
|
|
226
|
-
};
|
|
227
|
-
}
|
|
228
|
-
function fromTextStream(agent, defaultOptions) {
|
|
141
|
+
function fromTextStream(agent, options) {
|
|
142
|
+
const template = options?.template ?? defaultTextTemplate;
|
|
229
143
|
return (0, import_xstate.fromObservable)(({ input }) => {
|
|
230
144
|
const observers = /* @__PURE__ */ new Set();
|
|
231
145
|
(async () => {
|
|
232
|
-
const
|
|
233
|
-
|
|
234
|
-
|
|
146
|
+
const model = input.model ? agent.wrap(input.model) : agent.model;
|
|
147
|
+
const goal = typeof input.prompt === "string" ? input.prompt : await input.prompt(agent);
|
|
148
|
+
const promptWithContext = template({
|
|
149
|
+
goal,
|
|
235
150
|
context: input.context
|
|
236
151
|
});
|
|
152
|
+
const messages = await getMessages(agent, promptWithContext, input);
|
|
153
|
+
const result = await (0, import_ai.streamText)({
|
|
154
|
+
...options,
|
|
155
|
+
...input,
|
|
156
|
+
prompt: void 0,
|
|
157
|
+
// overwritten by messages
|
|
158
|
+
model,
|
|
159
|
+
messages
|
|
160
|
+
});
|
|
237
161
|
for await (const part of result.fullStream) {
|
|
238
162
|
if (part.type === "text-delta") {
|
|
239
163
|
observers.forEach((observer) => {
|
|
@@ -255,32 +179,89 @@ function fromTextStream(agent, defaultOptions) {
|
|
|
255
179
|
};
|
|
256
180
|
});
|
|
257
181
|
}
|
|
258
|
-
function fromText(agent,
|
|
182
|
+
function fromText(agent, options) {
|
|
183
|
+
const resolvedOptions = {
|
|
184
|
+
...agent.defaultOptions,
|
|
185
|
+
...options
|
|
186
|
+
};
|
|
187
|
+
const template = resolvedOptions.template ?? defaultTextTemplate;
|
|
259
188
|
return (0, import_xstate.fromPromise)(async ({ input }) => {
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
189
|
+
const goal = typeof input.prompt === "string" ? input.prompt : await input.prompt(agent);
|
|
190
|
+
const promptWithContext = template({
|
|
191
|
+
goal,
|
|
263
192
|
context: input.context
|
|
264
193
|
});
|
|
194
|
+
const messages = await getMessages(agent, promptWithContext, input);
|
|
195
|
+
const model = input.model ? agent.wrap(input.model) : agent.model;
|
|
196
|
+
return await (0, import_ai.generateText)({
|
|
197
|
+
...input,
|
|
198
|
+
...options,
|
|
199
|
+
prompt: void 0,
|
|
200
|
+
messages,
|
|
201
|
+
model
|
|
202
|
+
});
|
|
265
203
|
});
|
|
266
204
|
}
|
|
267
205
|
|
|
268
|
-
// src/
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
206
|
+
// src/decide.ts
|
|
207
|
+
var import_xstate2 = require("xstate");
|
|
208
|
+
var import_ai2 = require("ai");
|
|
209
|
+
async function agentDecide(agent, options) {
|
|
210
|
+
const resolvedOptions = {
|
|
211
|
+
...agent.defaultOptions,
|
|
212
|
+
...options
|
|
213
|
+
};
|
|
214
|
+
const {
|
|
215
|
+
planner = simplePlanner,
|
|
216
|
+
goal,
|
|
217
|
+
events = agent.events,
|
|
218
|
+
state,
|
|
219
|
+
machine,
|
|
220
|
+
model = agent.model,
|
|
221
|
+
...otherPlanInput
|
|
222
|
+
} = resolvedOptions;
|
|
223
|
+
const plan = await planner(agent, {
|
|
224
|
+
model,
|
|
225
|
+
goal,
|
|
226
|
+
events,
|
|
227
|
+
state,
|
|
228
|
+
machine,
|
|
229
|
+
...otherPlanInput
|
|
230
|
+
});
|
|
231
|
+
if (plan?.nextEvent) {
|
|
232
|
+
agent.addPlan(plan);
|
|
233
|
+
await resolvedOptions.execute?.(plan.nextEvent);
|
|
272
234
|
}
|
|
273
|
-
|
|
274
|
-
return getAllTransitions(resolvedState);
|
|
235
|
+
return plan;
|
|
275
236
|
}
|
|
276
|
-
|
|
277
|
-
return
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
237
|
+
function fromDecision(agent, defaultInput) {
|
|
238
|
+
return (0, import_xstate2.fromPromise)(async ({ input, self }) => {
|
|
239
|
+
const parentRef = self._parent;
|
|
240
|
+
if (!parentRef) {
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
const snapshot = parentRef.getSnapshot();
|
|
244
|
+
const inputObject = typeof input === "string" ? { goal: input } : input;
|
|
245
|
+
const resolvedInput = {
|
|
246
|
+
...defaultInput,
|
|
247
|
+
...inputObject
|
|
248
|
+
};
|
|
249
|
+
const state = {
|
|
250
|
+
value: snapshot.value,
|
|
251
|
+
context: resolvedInput.context
|
|
252
|
+
};
|
|
253
|
+
const plan = await agentDecide(agent, {
|
|
254
|
+
machine: parentRef.logic,
|
|
255
|
+
state,
|
|
256
|
+
execute: async (event) => {
|
|
257
|
+
parentRef.send(event);
|
|
258
|
+
},
|
|
259
|
+
...resolvedInput
|
|
260
|
+
});
|
|
261
|
+
return plan;
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
function getToolMap(_agent, input) {
|
|
284
265
|
const transitions = input.machine ? getTransitions(input.state, input.machine) : Object.entries(input.events).map(([eventType, { description }]) => ({
|
|
285
266
|
eventType,
|
|
286
267
|
description
|
|
@@ -305,7 +286,7 @@ async function simplePlanner(agent, input) {
|
|
|
305
286
|
if (!toolZodType) {
|
|
306
287
|
continue;
|
|
307
288
|
}
|
|
308
|
-
toolMap[toolTransitionData.name] = (0,
|
|
289
|
+
toolMap[toolTransitionData.name] = (0, import_ai2.tool)({
|
|
309
290
|
description: toolZodType?.description ?? toolTransitionData.description,
|
|
310
291
|
parameters: toolZodType,
|
|
311
292
|
execute: async (params) => {
|
|
@@ -320,17 +301,55 @@ async function simplePlanner(agent, input) {
|
|
|
320
301
|
if (!Object.keys(toolMap).length) {
|
|
321
302
|
return void 0;
|
|
322
303
|
}
|
|
304
|
+
return toolMap;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// src/planners/simplePlanner.ts
|
|
308
|
+
var simplePlannerPromptTemplate = (data) => {
|
|
309
|
+
return `
|
|
310
|
+
${defaultTextTemplate(data)}
|
|
311
|
+
|
|
312
|
+
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
|
+
`.trim();
|
|
314
|
+
};
|
|
315
|
+
async function simplePlanner(agent, input) {
|
|
316
|
+
const toolMap = getToolMap(agent, input);
|
|
317
|
+
if (!toolMap) {
|
|
318
|
+
return void 0;
|
|
319
|
+
}
|
|
323
320
|
const prompt = simplePlannerPromptTemplate({
|
|
324
321
|
context: input.state.context,
|
|
325
322
|
goal: input.goal
|
|
326
323
|
});
|
|
327
324
|
const messages = await getMessages(agent, prompt, input);
|
|
328
|
-
const
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
325
|
+
const model = input.model ? agent.wrap(input.model) : agent.model;
|
|
326
|
+
const {
|
|
327
|
+
state,
|
|
328
|
+
machine,
|
|
329
|
+
previousPlan,
|
|
330
|
+
events,
|
|
331
|
+
goal,
|
|
332
|
+
model: _,
|
|
333
|
+
...rest
|
|
334
|
+
} = input;
|
|
335
|
+
const machineState = input.machine ? input.machine.resolveState({
|
|
336
|
+
...input.state,
|
|
337
|
+
context: input.state.context
|
|
338
|
+
}) : void 0;
|
|
339
|
+
const result = await (0, import_ai3.generateText)({
|
|
340
|
+
...rest,
|
|
341
|
+
model,
|
|
332
342
|
messages,
|
|
333
|
-
tools: toolMap
|
|
343
|
+
tools: toolMap,
|
|
344
|
+
toolChoice: input.toolChoice ?? "required"
|
|
345
|
+
});
|
|
346
|
+
result.responseMessages.forEach((m) => {
|
|
347
|
+
const message = m;
|
|
348
|
+
agent.addMessage({
|
|
349
|
+
...message,
|
|
350
|
+
id: randomId(),
|
|
351
|
+
timestamp: Date.now()
|
|
352
|
+
});
|
|
334
353
|
});
|
|
335
354
|
const singleResult = result.toolResults[0];
|
|
336
355
|
if (!singleResult) {
|
|
@@ -338,91 +357,100 @@ async function simplePlanner(agent, input) {
|
|
|
338
357
|
return void 0;
|
|
339
358
|
}
|
|
340
359
|
return {
|
|
360
|
+
planner: "simple",
|
|
341
361
|
goal: input.goal,
|
|
342
|
-
|
|
343
|
-
execute: async (state) => {
|
|
344
|
-
if (JSON.stringify(state) === JSON.stringify(input.state)) {
|
|
345
|
-
return singleResult.result;
|
|
346
|
-
}
|
|
347
|
-
return void 0;
|
|
348
|
-
},
|
|
362
|
+
goalState: input.state,
|
|
349
363
|
nextEvent: singleResult.result,
|
|
350
|
-
|
|
351
|
-
timestamp: Date.now()
|
|
364
|
+
episodeId: agent.episodeId,
|
|
365
|
+
timestamp: Date.now(),
|
|
366
|
+
paths: [
|
|
367
|
+
{
|
|
368
|
+
state: void 0,
|
|
369
|
+
steps: [
|
|
370
|
+
{
|
|
371
|
+
event: singleResult.result,
|
|
372
|
+
state: machine && machineState ? (0, import_xstate3.getNextSnapshot)(machine, machineState, singleResult.result) : void 0
|
|
373
|
+
}
|
|
374
|
+
]
|
|
375
|
+
}
|
|
376
|
+
]
|
|
352
377
|
};
|
|
353
378
|
}
|
|
354
379
|
|
|
355
|
-
// src/
|
|
356
|
-
var
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
380
|
+
// src/agent.ts
|
|
381
|
+
var import_ai4 = require("ai");
|
|
382
|
+
|
|
383
|
+
// src/middleware.ts
|
|
384
|
+
function createAgentMiddleware(agent) {
|
|
385
|
+
const middleware = {
|
|
386
|
+
transformParams: async ({ params }) => {
|
|
387
|
+
return params;
|
|
388
|
+
},
|
|
389
|
+
wrapGenerate: async ({ doGenerate, params }) => {
|
|
390
|
+
const id = randomId();
|
|
391
|
+
params.prompt.forEach((p) => {
|
|
392
|
+
agent.addMessage({
|
|
393
|
+
id,
|
|
394
|
+
...p,
|
|
395
|
+
timestamp: Date.now(),
|
|
396
|
+
correlationId: params.providerMetadata?.correlationId,
|
|
397
|
+
parentCorrelationId: params.providerMetadata?.parentCorrelationId
|
|
398
|
+
});
|
|
399
|
+
});
|
|
400
|
+
const result = await doGenerate();
|
|
401
|
+
return result;
|
|
402
|
+
},
|
|
403
|
+
wrapStream: async ({ doStream, params }) => {
|
|
404
|
+
const id = randomId();
|
|
405
|
+
params.prompt.forEach((message) => {
|
|
406
|
+
message.content;
|
|
407
|
+
agent.addMessage({
|
|
408
|
+
id,
|
|
409
|
+
...message,
|
|
410
|
+
timestamp: Date.now(),
|
|
411
|
+
correlationId: params.providerMetadata?.correlationId,
|
|
412
|
+
parentCorrelationId: params.providerMetadata?.parentCorrelationId
|
|
413
|
+
});
|
|
414
|
+
});
|
|
415
|
+
const { stream, ...rest } = await doStream();
|
|
416
|
+
let generatedText = "";
|
|
417
|
+
const transformStream = new TransformStream({
|
|
418
|
+
transform(chunk, controller) {
|
|
419
|
+
if (chunk.type === "text-delta") {
|
|
420
|
+
generatedText += chunk.textDelta;
|
|
421
|
+
}
|
|
422
|
+
controller.enqueue(chunk);
|
|
423
|
+
},
|
|
424
|
+
flush() {
|
|
425
|
+
const content = [];
|
|
426
|
+
if (generatedText) {
|
|
427
|
+
content.push({
|
|
428
|
+
type: "text",
|
|
429
|
+
text: generatedText
|
|
430
|
+
});
|
|
431
|
+
}
|
|
432
|
+
agent.addMessage({
|
|
433
|
+
id: randomId(),
|
|
434
|
+
timestamp: Date.now(),
|
|
435
|
+
role: "assistant",
|
|
436
|
+
content,
|
|
437
|
+
responseId: id,
|
|
438
|
+
correlationId: params.providerMetadata?.correlationId,
|
|
439
|
+
parentCorrelationId: params.providerMetadata?.parentCorrelationId
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
});
|
|
443
|
+
return {
|
|
444
|
+
stream: stream.pipeThrough(transformStream),
|
|
445
|
+
...rest
|
|
446
|
+
};
|
|
390
447
|
}
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
const resolvedInput = {
|
|
394
|
-
...defaultInput,
|
|
395
|
-
...inputObject
|
|
396
|
-
};
|
|
397
|
-
const contextToInclude = resolvedInput.context === true ? (
|
|
398
|
-
// include entire context
|
|
399
|
-
parentRef.getSnapshot().context
|
|
400
|
-
) : resolvedInput.context;
|
|
401
|
-
const state = {
|
|
402
|
-
value: snapshot.value,
|
|
403
|
-
context: contextToInclude
|
|
404
|
-
};
|
|
405
|
-
const plan = await agentDecide(agent, {
|
|
406
|
-
machine: parentRef.logic,
|
|
407
|
-
state,
|
|
408
|
-
execute: async (event) => {
|
|
409
|
-
parentRef.send(event);
|
|
410
|
-
},
|
|
411
|
-
...resolvedInput
|
|
412
|
-
});
|
|
413
|
-
return plan;
|
|
414
|
-
});
|
|
448
|
+
};
|
|
449
|
+
return middleware;
|
|
415
450
|
}
|
|
416
451
|
|
|
417
|
-
// src/adapters/vercel.ts
|
|
418
|
-
var import_ai2 = require("ai");
|
|
419
|
-
var vercelAdapter = {
|
|
420
|
-
generateText: import_ai2.generateText,
|
|
421
|
-
streamText: import_ai2.streamText
|
|
422
|
-
};
|
|
423
|
-
|
|
424
452
|
// src/agent.ts
|
|
425
|
-
var agentLogic = (0,
|
|
453
|
+
var agentLogic = (0, import_xstate4.fromTransition)(
|
|
426
454
|
(state, event, { emit }) => {
|
|
427
455
|
switch (event.type) {
|
|
428
456
|
case "agent.feedback": {
|
|
@@ -474,6 +502,7 @@ var agentLogic = (0, import_xstate3.fromTransition)(
|
|
|
474
502
|
})
|
|
475
503
|
);
|
|
476
504
|
function createAgent({
|
|
505
|
+
id,
|
|
477
506
|
name,
|
|
478
507
|
description,
|
|
479
508
|
model,
|
|
@@ -483,92 +512,133 @@ function createAgent({
|
|
|
483
512
|
stringify = JSON.stringify,
|
|
484
513
|
getMemory,
|
|
485
514
|
logic = agentLogic,
|
|
486
|
-
adapter = vercelAdapter,
|
|
487
515
|
...generateTextOptions
|
|
488
516
|
}) {
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
};
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
517
|
+
return new Agent({
|
|
518
|
+
id,
|
|
519
|
+
context,
|
|
520
|
+
events,
|
|
521
|
+
name,
|
|
522
|
+
description,
|
|
523
|
+
planner,
|
|
524
|
+
model,
|
|
525
|
+
logic
|
|
526
|
+
});
|
|
527
|
+
}
|
|
528
|
+
var Agent = class extends import_xstate4.Actor {
|
|
529
|
+
// todo
|
|
530
|
+
constructor({
|
|
531
|
+
logic = agentLogic,
|
|
532
|
+
id,
|
|
533
|
+
name,
|
|
534
|
+
description,
|
|
535
|
+
model,
|
|
536
|
+
events,
|
|
537
|
+
context,
|
|
538
|
+
planner = simplePlanner
|
|
539
|
+
}) {
|
|
540
|
+
super(logic);
|
|
541
|
+
this.model = model;
|
|
542
|
+
this.episodeId = id ?? randomId();
|
|
543
|
+
this.name = name;
|
|
544
|
+
this.description = description;
|
|
545
|
+
this.events = events;
|
|
546
|
+
this.context = context;
|
|
547
|
+
this.planner = planner;
|
|
548
|
+
this.types = {};
|
|
549
|
+
this.start();
|
|
550
|
+
}
|
|
551
|
+
/**
|
|
552
|
+
* Called whenever the agent (LLM assistant) receives or sends a message.
|
|
553
|
+
*/
|
|
554
|
+
onMessage(fn) {
|
|
555
|
+
return this.on("message", (ev) => fn(ev.message));
|
|
556
|
+
}
|
|
557
|
+
/**
|
|
558
|
+
* Retrieves messages from the agent's short-term (local) memory.
|
|
559
|
+
*/
|
|
560
|
+
addMessage(messageInput) {
|
|
507
561
|
const message = {
|
|
508
562
|
...messageInput,
|
|
509
563
|
id: messageInput.id ?? randomId(),
|
|
510
564
|
timestamp: messageInput.timestamp ?? Date.now(),
|
|
511
|
-
|
|
512
|
-
correlationId: messageInput.correlationId ?? randomId()
|
|
565
|
+
episodeId: this.episodeId
|
|
513
566
|
};
|
|
514
|
-
|
|
567
|
+
this.send({
|
|
515
568
|
type: "agent.message",
|
|
516
569
|
message
|
|
517
570
|
});
|
|
518
571
|
return message;
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
572
|
+
}
|
|
573
|
+
getMessages() {
|
|
574
|
+
return this.getSnapshot().context.messages;
|
|
575
|
+
}
|
|
576
|
+
addFeedback(feedbackInput) {
|
|
524
577
|
const feedback = {
|
|
525
578
|
...feedbackInput,
|
|
526
579
|
attributes: { ...feedbackInput.attributes },
|
|
527
580
|
reward: feedbackInput.reward ?? 0,
|
|
528
581
|
timestamp: feedbackInput.timestamp ?? Date.now(),
|
|
529
|
-
|
|
582
|
+
episodeId: this.episodeId
|
|
530
583
|
};
|
|
531
|
-
|
|
584
|
+
this.send({
|
|
532
585
|
type: "agent.feedback",
|
|
533
586
|
feedback
|
|
534
587
|
});
|
|
535
588
|
return feedback;
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
|
|
589
|
+
}
|
|
590
|
+
/**
|
|
591
|
+
* Retrieves feedback from the agent's short-term (local) memory.
|
|
592
|
+
*/
|
|
593
|
+
getFeedback() {
|
|
594
|
+
return this.getSnapshot().context.feedback;
|
|
595
|
+
}
|
|
596
|
+
addObservation(observationInput) {
|
|
539
597
|
const { prevState, event, state } = observationInput;
|
|
540
598
|
const observation = {
|
|
541
599
|
prevState,
|
|
542
600
|
event,
|
|
543
601
|
state,
|
|
544
602
|
id: observationInput.id ?? randomId(),
|
|
545
|
-
|
|
603
|
+
episodeId: this.episodeId,
|
|
546
604
|
timestamp: observationInput.timestamp ?? Date.now(),
|
|
547
605
|
machineHash: observationInput.machine ? getMachineHash(observationInput.machine) : void 0
|
|
548
606
|
};
|
|
549
|
-
|
|
607
|
+
this.send({
|
|
550
608
|
type: "agent.observe",
|
|
551
609
|
observation
|
|
552
610
|
});
|
|
553
611
|
return observation;
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
612
|
+
}
|
|
613
|
+
/**
|
|
614
|
+
* Retrieves observations from the agent's short-term (local) memory.
|
|
615
|
+
*/
|
|
616
|
+
getObservations() {
|
|
617
|
+
return this.getSnapshot().context.observations;
|
|
618
|
+
}
|
|
619
|
+
addPlan(plan) {
|
|
620
|
+
this.send({
|
|
558
621
|
type: "agent.plan",
|
|
559
622
|
plan
|
|
560
623
|
});
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
|
|
624
|
+
}
|
|
625
|
+
/**
|
|
626
|
+
* Retrieves strategies from the agent's short-term (local) memory.
|
|
627
|
+
*/
|
|
628
|
+
getPlans() {
|
|
629
|
+
return this.getSnapshot().context.plans;
|
|
630
|
+
}
|
|
631
|
+
interact(actorRef, getInput) {
|
|
632
|
+
const actorRefCheck = isActorRef(actorRef);
|
|
564
633
|
let prevState = void 0;
|
|
565
634
|
let subscribed = true;
|
|
635
|
+
const agent = this;
|
|
566
636
|
async function handleObservation(observationInput) {
|
|
567
637
|
const observation = agent.addObservation(observationInput);
|
|
568
638
|
const input = getInput?.(observation);
|
|
569
639
|
if (input) {
|
|
570
640
|
await agentDecide(agent, {
|
|
571
|
-
machine: actorRef.src,
|
|
641
|
+
machine: actorRefCheck ? actorRef.src : void 0,
|
|
572
642
|
state: observation.state,
|
|
573
643
|
execute: async (event) => {
|
|
574
644
|
actorRef.send(event);
|
|
@@ -578,7 +648,7 @@ function createAgent({
|
|
|
578
648
|
}
|
|
579
649
|
prevState = observationInput.state;
|
|
580
650
|
}
|
|
581
|
-
actorRef.system.inspect({
|
|
651
|
+
const sub = actorRefCheck ? actorRef.system.inspect({
|
|
582
652
|
next: async (inspEvent) => {
|
|
583
653
|
if (!subscribed || inspEvent.actorRef !== actorRef || inspEvent.type !== "@xstate.snapshot") {
|
|
584
654
|
return;
|
|
@@ -591,7 +661,7 @@ function createAgent({
|
|
|
591
661
|
};
|
|
592
662
|
await handleObservation(observationInput);
|
|
593
663
|
}
|
|
594
|
-
});
|
|
664
|
+
}) : void 0;
|
|
595
665
|
if (actorRef._processingStatus === 1) {
|
|
596
666
|
handleObservation({
|
|
597
667
|
prevState: void 0,
|
|
@@ -603,15 +673,50 @@ function createAgent({
|
|
|
603
673
|
}
|
|
604
674
|
return {
|
|
605
675
|
unsubscribe: () => {
|
|
676
|
+
sub?.unsubscribe();
|
|
606
677
|
subscribed = false;
|
|
607
678
|
}
|
|
608
|
-
// TODO: make this actually unsubscribe
|
|
609
679
|
};
|
|
610
|
-
}
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
680
|
+
}
|
|
681
|
+
observe(actorRef) {
|
|
682
|
+
let prevState = actorRef.getSnapshot();
|
|
683
|
+
const actorRefCheck = isActorRef(actorRef);
|
|
684
|
+
const sub = actorRefCheck ? actorRef.system.inspect({
|
|
685
|
+
next: async (inspEvent) => {
|
|
686
|
+
if (inspEvent.actorRef !== actorRef || inspEvent.type !== "@xstate.snapshot") {
|
|
687
|
+
return;
|
|
688
|
+
}
|
|
689
|
+
const observationInput = {
|
|
690
|
+
event: inspEvent.event,
|
|
691
|
+
prevState,
|
|
692
|
+
state: inspEvent.snapshot,
|
|
693
|
+
machine: actorRef.src
|
|
694
|
+
};
|
|
695
|
+
prevState = observationInput.state;
|
|
696
|
+
this.addObservation(observationInput);
|
|
697
|
+
}
|
|
698
|
+
}) : void 0;
|
|
699
|
+
return sub ?? { unsubscribe: () => {
|
|
700
|
+
} };
|
|
701
|
+
}
|
|
702
|
+
wrap(modelToWrap) {
|
|
703
|
+
return (0, import_ai4.experimental_wrapLanguageModel)({
|
|
704
|
+
model: modelToWrap,
|
|
705
|
+
middleware: createAgentMiddleware(this)
|
|
706
|
+
});
|
|
707
|
+
}
|
|
708
|
+
/**
|
|
709
|
+
* Resolves with an `AgentPlan` based on the information provided in the `options`, including:
|
|
710
|
+
*
|
|
711
|
+
* - The `goal` for the agent to achieve
|
|
712
|
+
* - The observed current `state`
|
|
713
|
+
* - The `machine` (e.g. a state machine) that specifies what can happen next
|
|
714
|
+
* - Additional `context`
|
|
715
|
+
*/
|
|
716
|
+
decide(opts) {
|
|
717
|
+
return agentDecide(this, opts);
|
|
718
|
+
}
|
|
719
|
+
};
|
|
615
720
|
// Annotate the CommonJS export names for ESM import in node:
|
|
616
721
|
0 && (module.exports = {
|
|
617
722
|
createAgent,
|