@statelyai/agent 2.0.0-next.3 → 2.0.0-next.4
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/nice-pants-rule.md +10 -0
- package/.changeset/pre.json +1 -0
- package/CHANGELOG.md +11 -0
- package/architecture.tldr +175 -0
- package/dist/index.d.mts +44 -37
- package/dist/index.d.ts +44 -37
- package/dist/index.js +28 -53
- package/dist/index.mjs +28 -53
- package/examples/learn-from-feedback.ts +2 -2
- package/package.json +1 -1
- package/src/agent.test.ts +106 -8
- package/src/agent.ts +14 -15
- package/src/decide.test.ts +22 -0
- package/src/decide.ts +16 -18
- package/src/strategies/chainOfThought.ts +1 -1
- package/src/strategies/{simple.ts → simpleStrategy.ts} +1 -1
- package/src/text.ts +0 -1
- package/src/types.ts +27 -35
package/dist/index.js
CHANGED
|
@@ -40,7 +40,7 @@ module.exports = __toCommonJS(src_exports);
|
|
|
40
40
|
// src/agent.ts
|
|
41
41
|
var import_xstate4 = require("xstate");
|
|
42
42
|
|
|
43
|
-
// src/strategies/
|
|
43
|
+
// src/strategies/simpleStrategy.ts
|
|
44
44
|
var import_ai3 = require("ai");
|
|
45
45
|
|
|
46
46
|
// src/utils.ts
|
|
@@ -60,22 +60,6 @@ function getAllTransitions(state) {
|
|
|
60
60
|
}).flat(2);
|
|
61
61
|
return transitions;
|
|
62
62
|
}
|
|
63
|
-
function getAllMachineTransitions(stateNode) {
|
|
64
|
-
const transitions = [...stateNode.transitions.values()].map((nodeTransitions) => {
|
|
65
|
-
return nodeTransitions.map((transition) => {
|
|
66
|
-
return {
|
|
67
|
-
...transition,
|
|
68
|
-
guard: typeof transition.guard === "string" ? { type: transition.guard } : transition.guard
|
|
69
|
-
// TODO: fix
|
|
70
|
-
};
|
|
71
|
-
});
|
|
72
|
-
}).flat(2);
|
|
73
|
-
for (const s of Object.values(stateNode.states)) {
|
|
74
|
-
const stateTransitions = getAllMachineTransitions(s);
|
|
75
|
-
transitions.push(...stateTransitions);
|
|
76
|
-
}
|
|
77
|
-
return transitions;
|
|
78
|
-
}
|
|
79
63
|
function wrapInXml(tagName, content) {
|
|
80
64
|
return `<${tagName}>${content}</${tagName}>`;
|
|
81
65
|
}
|
|
@@ -93,14 +77,6 @@ function randomId(prefix) {
|
|
|
93
77
|
const random = Math.random().toString(36).substring(2, 9);
|
|
94
78
|
return `${prefix || ""}${timestamp}${random}`;
|
|
95
79
|
}
|
|
96
|
-
var machineHashes = /* @__PURE__ */ new WeakMap();
|
|
97
|
-
function getMachineHash(machine) {
|
|
98
|
-
if (machineHashes.has(machine)) return machineHashes.get(machine);
|
|
99
|
-
const transitions = getAllMachineTransitions(machine.root);
|
|
100
|
-
const machineHash = (0, import_object_hash.default)(transitions);
|
|
101
|
-
machineHashes.set(machine, machineHash);
|
|
102
|
-
return machineHash;
|
|
103
|
-
}
|
|
104
80
|
function isActorRef(actorRefLike) {
|
|
105
81
|
return "src" in actorRefLike && "system" in actorRefLike && "sessionId" in actorRefLike;
|
|
106
82
|
}
|
|
@@ -119,7 +95,7 @@ function isMachineActor(actor) {
|
|
|
119
95
|
return "src" in actor && typeof actor.src === "object" && actor.src !== null && "definition" in actor.src;
|
|
120
96
|
}
|
|
121
97
|
|
|
122
|
-
// src/strategies/
|
|
98
|
+
// src/strategies/simpleStrategy.ts
|
|
123
99
|
var import_xstate3 = require("xstate");
|
|
124
100
|
|
|
125
101
|
// src/text.ts
|
|
@@ -196,7 +172,6 @@ function fromTextStream(agent, options) {
|
|
|
196
172
|
}
|
|
197
173
|
function fromText(agent, options) {
|
|
198
174
|
const resolvedOptions = {
|
|
199
|
-
...agent.defaultOptions,
|
|
200
175
|
...options
|
|
201
176
|
};
|
|
202
177
|
const template = resolvedOptions.template ?? defaultTextTemplate;
|
|
@@ -222,10 +197,7 @@ function fromText(agent, options) {
|
|
|
222
197
|
var import_xstate2 = require("xstate");
|
|
223
198
|
var import_ai2 = require("ai");
|
|
224
199
|
async function agentDecide(agent, options) {
|
|
225
|
-
const resolvedOptions =
|
|
226
|
-
...agent.defaultOptions,
|
|
227
|
-
...options
|
|
228
|
-
};
|
|
200
|
+
const resolvedOptions = options;
|
|
229
201
|
const {
|
|
230
202
|
strategy = agent.strategy,
|
|
231
203
|
goal,
|
|
@@ -235,6 +207,8 @@ async function agentDecide(agent, options) {
|
|
|
235
207
|
machine,
|
|
236
208
|
model = agent.model,
|
|
237
209
|
messages,
|
|
210
|
+
episodeId = agent.episodeId,
|
|
211
|
+
maxAttempts = 2,
|
|
238
212
|
...otherDecideInput
|
|
239
213
|
} = resolvedOptions;
|
|
240
214
|
const filteredEventSchemas = allowedEvents ? Object.fromEntries(
|
|
@@ -243,7 +217,6 @@ async function agentDecide(agent, options) {
|
|
|
243
217
|
})
|
|
244
218
|
) : events;
|
|
245
219
|
let attempts = 0;
|
|
246
|
-
const maxAttempts = resolvedOptions.maxAttempts ?? 2;
|
|
247
220
|
let decision;
|
|
248
221
|
const minimalState = {
|
|
249
222
|
value: state.value,
|
|
@@ -251,6 +224,7 @@ async function agentDecide(agent, options) {
|
|
|
251
224
|
};
|
|
252
225
|
while (attempts++ < maxAttempts) {
|
|
253
226
|
decision = await strategy(agent, {
|
|
227
|
+
episodeId,
|
|
254
228
|
model,
|
|
255
229
|
goal,
|
|
256
230
|
events: filteredEventSchemas,
|
|
@@ -262,7 +236,6 @@ async function agentDecide(agent, options) {
|
|
|
262
236
|
});
|
|
263
237
|
if (decision?.nextEvent) {
|
|
264
238
|
agent.addDecision(decision);
|
|
265
|
-
await resolvedOptions.execute?.(decision.nextEvent);
|
|
266
239
|
break;
|
|
267
240
|
}
|
|
268
241
|
}
|
|
@@ -283,22 +256,23 @@ function fromDecision(agent, defaultInput) {
|
|
|
283
256
|
const decision = await agentDecide(agent, {
|
|
284
257
|
machine: parentRef.logic,
|
|
285
258
|
state: snapshot,
|
|
286
|
-
execute: async (event) => {
|
|
287
|
-
parentRef.send(event);
|
|
288
|
-
},
|
|
289
259
|
...resolvedInput,
|
|
290
260
|
// @ts-ignore
|
|
291
261
|
messages: resolvedInput.messages
|
|
292
262
|
});
|
|
263
|
+
if (decision?.nextEvent) {
|
|
264
|
+
parentRef.send(decision.nextEvent);
|
|
265
|
+
}
|
|
293
266
|
return decision;
|
|
294
267
|
});
|
|
295
268
|
}
|
|
296
|
-
function getToolMap(
|
|
297
|
-
const
|
|
269
|
+
function getToolMap(agent, input) {
|
|
270
|
+
const events = input.events ?? agent.events;
|
|
271
|
+
const transitions = input.machine ? getTransitions(input.state, input.machine) : Object.entries(events).map(([eventType, { description }]) => ({
|
|
298
272
|
eventType,
|
|
299
273
|
description
|
|
300
274
|
}));
|
|
301
|
-
const filter = (eventType) => Object.keys(
|
|
275
|
+
const filter = (eventType) => Object.keys(events).includes(eventType);
|
|
302
276
|
const functionNameMapping = {};
|
|
303
277
|
const toolTransitions = transitions.filter((t) => {
|
|
304
278
|
return filter(t.eventType);
|
|
@@ -336,7 +310,7 @@ function getToolMap(_agent, input) {
|
|
|
336
310
|
return toolMap;
|
|
337
311
|
}
|
|
338
312
|
|
|
339
|
-
// src/strategies/
|
|
313
|
+
// src/strategies/simpleStrategy.ts
|
|
340
314
|
var simpleStrategyPromptTemplate = (data) => {
|
|
341
315
|
return `
|
|
342
316
|
${convertToXml(data)}
|
|
@@ -388,7 +362,7 @@ async function simpleStrategy(agent, input) {
|
|
|
388
362
|
goal: input.goal,
|
|
389
363
|
goalState: input.state,
|
|
390
364
|
nextEvent: singleResult.result,
|
|
391
|
-
episodeId: agent.episodeId,
|
|
365
|
+
episodeId: input.episodeId ?? agent.episodeId,
|
|
392
366
|
timestamp: Date.now(),
|
|
393
367
|
paths: [
|
|
394
368
|
{
|
|
@@ -545,7 +519,6 @@ function createAgent({
|
|
|
545
519
|
});
|
|
546
520
|
}
|
|
547
521
|
var Agent = class extends import_xstate4.Actor {
|
|
548
|
-
// todo
|
|
549
522
|
constructor({
|
|
550
523
|
logic = agentLogic,
|
|
551
524
|
id,
|
|
@@ -605,7 +578,7 @@ var Agent = class extends import_xstate4.Actor {
|
|
|
605
578
|
comment: feedbackInput.comment ?? void 0,
|
|
606
579
|
attributes: { ...feedbackInput.attributes },
|
|
607
580
|
timestamp: feedbackInput.timestamp ?? Date.now(),
|
|
608
|
-
episodeId: this.episodeId
|
|
581
|
+
episodeId: feedbackInput.episodeId ?? this.episodeId
|
|
609
582
|
};
|
|
610
583
|
this.send({
|
|
611
584
|
type: "agent.feedback",
|
|
@@ -626,9 +599,12 @@ var Agent = class extends import_xstate4.Actor {
|
|
|
626
599
|
event,
|
|
627
600
|
state,
|
|
628
601
|
id: observationInput.id ?? randomId(),
|
|
629
|
-
episodeId: this.episodeId,
|
|
602
|
+
episodeId: observationInput.episodeId ?? this.episodeId,
|
|
630
603
|
timestamp: observationInput.timestamp ?? Date.now(),
|
|
631
|
-
|
|
604
|
+
decisionId: observationInput.decisionId
|
|
605
|
+
// machineHash: observationInput.machine
|
|
606
|
+
// ? getMachineHash(observationInput.machine)
|
|
607
|
+
// : undefined,
|
|
632
608
|
};
|
|
633
609
|
this.send({
|
|
634
610
|
type: "agent.observe",
|
|
@@ -687,19 +663,18 @@ var Agent = class extends import_xstate4.Actor {
|
|
|
687
663
|
event: inspEvent.event,
|
|
688
664
|
prevState,
|
|
689
665
|
state: inspEvent.snapshot,
|
|
690
|
-
|
|
691
|
-
|
|
666
|
+
goal: decision?.goal,
|
|
667
|
+
decisionId
|
|
692
668
|
};
|
|
693
669
|
await handleObservation(observationInput);
|
|
694
670
|
}
|
|
695
671
|
}) : void 0;
|
|
696
672
|
if (actorRef._processingStatus === 1) {
|
|
697
673
|
handleObservation({
|
|
674
|
+
decisionId: void 0,
|
|
698
675
|
prevState: void 0,
|
|
699
676
|
event: void 0,
|
|
700
|
-
state: actorRef.getSnapshot()
|
|
701
|
-
machine: actorRef.src,
|
|
702
|
-
goal: void 0
|
|
677
|
+
state: actorRef.getSnapshot()
|
|
703
678
|
});
|
|
704
679
|
}
|
|
705
680
|
return {
|
|
@@ -720,10 +695,10 @@ var Agent = class extends import_xstate4.Actor {
|
|
|
720
695
|
const decisionId = inspEvent.event["_decision"];
|
|
721
696
|
const decision = decisionId ? this.getDecisions().find((d) => d.id === decisionId) : void 0;
|
|
722
697
|
const observationInput = {
|
|
698
|
+
decisionId,
|
|
723
699
|
event: inspEvent.event,
|
|
724
700
|
prevState,
|
|
725
701
|
state: inspEvent.snapshot,
|
|
726
|
-
machine: actorRef.src,
|
|
727
702
|
goal: decision?.goal
|
|
728
703
|
};
|
|
729
704
|
prevState = observationInput.state;
|
|
@@ -747,8 +722,8 @@ var Agent = class extends import_xstate4.Actor {
|
|
|
747
722
|
* - The `machine` (e.g. a state machine) that specifies what can happen next
|
|
748
723
|
* - Additional `context`
|
|
749
724
|
*/
|
|
750
|
-
async decide(
|
|
751
|
-
return agentDecide(this,
|
|
725
|
+
async decide(input) {
|
|
726
|
+
return agentDecide(this, input);
|
|
752
727
|
}
|
|
753
728
|
};
|
|
754
729
|
// Annotate the CommonJS export names for ESM import in node:
|
package/dist/index.mjs
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
fromTransition
|
|
5
5
|
} from "xstate";
|
|
6
6
|
|
|
7
|
-
// src/strategies/
|
|
7
|
+
// src/strategies/simpleStrategy.ts
|
|
8
8
|
import { generateText as generateText2 } from "ai";
|
|
9
9
|
|
|
10
10
|
// src/utils.ts
|
|
@@ -24,22 +24,6 @@ function getAllTransitions(state) {
|
|
|
24
24
|
}).flat(2);
|
|
25
25
|
return transitions;
|
|
26
26
|
}
|
|
27
|
-
function getAllMachineTransitions(stateNode) {
|
|
28
|
-
const transitions = [...stateNode.transitions.values()].map((nodeTransitions) => {
|
|
29
|
-
return nodeTransitions.map((transition) => {
|
|
30
|
-
return {
|
|
31
|
-
...transition,
|
|
32
|
-
guard: typeof transition.guard === "string" ? { type: transition.guard } : transition.guard
|
|
33
|
-
// TODO: fix
|
|
34
|
-
};
|
|
35
|
-
});
|
|
36
|
-
}).flat(2);
|
|
37
|
-
for (const s of Object.values(stateNode.states)) {
|
|
38
|
-
const stateTransitions = getAllMachineTransitions(s);
|
|
39
|
-
transitions.push(...stateTransitions);
|
|
40
|
-
}
|
|
41
|
-
return transitions;
|
|
42
|
-
}
|
|
43
27
|
function wrapInXml(tagName, content) {
|
|
44
28
|
return `<${tagName}>${content}</${tagName}>`;
|
|
45
29
|
}
|
|
@@ -57,14 +41,6 @@ function randomId(prefix) {
|
|
|
57
41
|
const random = Math.random().toString(36).substring(2, 9);
|
|
58
42
|
return `${prefix || ""}${timestamp}${random}`;
|
|
59
43
|
}
|
|
60
|
-
var machineHashes = /* @__PURE__ */ new WeakMap();
|
|
61
|
-
function getMachineHash(machine) {
|
|
62
|
-
if (machineHashes.has(machine)) return machineHashes.get(machine);
|
|
63
|
-
const transitions = getAllMachineTransitions(machine.root);
|
|
64
|
-
const machineHash = hash(transitions);
|
|
65
|
-
machineHashes.set(machine, machineHash);
|
|
66
|
-
return machineHash;
|
|
67
|
-
}
|
|
68
44
|
function isActorRef(actorRefLike) {
|
|
69
45
|
return "src" in actorRefLike && "system" in actorRefLike && "sessionId" in actorRefLike;
|
|
70
46
|
}
|
|
@@ -83,7 +59,7 @@ function isMachineActor(actor) {
|
|
|
83
59
|
return "src" in actor && typeof actor.src === "object" && actor.src !== null && "definition" in actor.src;
|
|
84
60
|
}
|
|
85
61
|
|
|
86
|
-
// src/strategies/
|
|
62
|
+
// src/strategies/simpleStrategy.ts
|
|
87
63
|
import { getNextSnapshot } from "xstate";
|
|
88
64
|
|
|
89
65
|
// src/text.ts
|
|
@@ -167,7 +143,6 @@ function fromTextStream(agent, options) {
|
|
|
167
143
|
}
|
|
168
144
|
function fromText(agent, options) {
|
|
169
145
|
const resolvedOptions = {
|
|
170
|
-
...agent.defaultOptions,
|
|
171
146
|
...options
|
|
172
147
|
};
|
|
173
148
|
const template = resolvedOptions.template ?? defaultTextTemplate;
|
|
@@ -193,10 +168,7 @@ function fromText(agent, options) {
|
|
|
193
168
|
import { fromPromise as fromPromise2 } from "xstate";
|
|
194
169
|
import { tool } from "ai";
|
|
195
170
|
async function agentDecide(agent, options) {
|
|
196
|
-
const resolvedOptions =
|
|
197
|
-
...agent.defaultOptions,
|
|
198
|
-
...options
|
|
199
|
-
};
|
|
171
|
+
const resolvedOptions = options;
|
|
200
172
|
const {
|
|
201
173
|
strategy = agent.strategy,
|
|
202
174
|
goal,
|
|
@@ -206,6 +178,8 @@ async function agentDecide(agent, options) {
|
|
|
206
178
|
machine,
|
|
207
179
|
model = agent.model,
|
|
208
180
|
messages,
|
|
181
|
+
episodeId = agent.episodeId,
|
|
182
|
+
maxAttempts = 2,
|
|
209
183
|
...otherDecideInput
|
|
210
184
|
} = resolvedOptions;
|
|
211
185
|
const filteredEventSchemas = allowedEvents ? Object.fromEntries(
|
|
@@ -214,7 +188,6 @@ async function agentDecide(agent, options) {
|
|
|
214
188
|
})
|
|
215
189
|
) : events;
|
|
216
190
|
let attempts = 0;
|
|
217
|
-
const maxAttempts = resolvedOptions.maxAttempts ?? 2;
|
|
218
191
|
let decision;
|
|
219
192
|
const minimalState = {
|
|
220
193
|
value: state.value,
|
|
@@ -222,6 +195,7 @@ async function agentDecide(agent, options) {
|
|
|
222
195
|
};
|
|
223
196
|
while (attempts++ < maxAttempts) {
|
|
224
197
|
decision = await strategy(agent, {
|
|
198
|
+
episodeId,
|
|
225
199
|
model,
|
|
226
200
|
goal,
|
|
227
201
|
events: filteredEventSchemas,
|
|
@@ -233,7 +207,6 @@ async function agentDecide(agent, options) {
|
|
|
233
207
|
});
|
|
234
208
|
if (decision?.nextEvent) {
|
|
235
209
|
agent.addDecision(decision);
|
|
236
|
-
await resolvedOptions.execute?.(decision.nextEvent);
|
|
237
210
|
break;
|
|
238
211
|
}
|
|
239
212
|
}
|
|
@@ -254,22 +227,23 @@ function fromDecision(agent, defaultInput) {
|
|
|
254
227
|
const decision = await agentDecide(agent, {
|
|
255
228
|
machine: parentRef.logic,
|
|
256
229
|
state: snapshot,
|
|
257
|
-
execute: async (event) => {
|
|
258
|
-
parentRef.send(event);
|
|
259
|
-
},
|
|
260
230
|
...resolvedInput,
|
|
261
231
|
// @ts-ignore
|
|
262
232
|
messages: resolvedInput.messages
|
|
263
233
|
});
|
|
234
|
+
if (decision?.nextEvent) {
|
|
235
|
+
parentRef.send(decision.nextEvent);
|
|
236
|
+
}
|
|
264
237
|
return decision;
|
|
265
238
|
});
|
|
266
239
|
}
|
|
267
|
-
function getToolMap(
|
|
268
|
-
const
|
|
240
|
+
function getToolMap(agent, input) {
|
|
241
|
+
const events = input.events ?? agent.events;
|
|
242
|
+
const transitions = input.machine ? getTransitions(input.state, input.machine) : Object.entries(events).map(([eventType, { description }]) => ({
|
|
269
243
|
eventType,
|
|
270
244
|
description
|
|
271
245
|
}));
|
|
272
|
-
const filter = (eventType) => Object.keys(
|
|
246
|
+
const filter = (eventType) => Object.keys(events).includes(eventType);
|
|
273
247
|
const functionNameMapping = {};
|
|
274
248
|
const toolTransitions = transitions.filter((t) => {
|
|
275
249
|
return filter(t.eventType);
|
|
@@ -307,7 +281,7 @@ function getToolMap(_agent, input) {
|
|
|
307
281
|
return toolMap;
|
|
308
282
|
}
|
|
309
283
|
|
|
310
|
-
// src/strategies/
|
|
284
|
+
// src/strategies/simpleStrategy.ts
|
|
311
285
|
var simpleStrategyPromptTemplate = (data) => {
|
|
312
286
|
return `
|
|
313
287
|
${convertToXml(data)}
|
|
@@ -359,7 +333,7 @@ async function simpleStrategy(agent, input) {
|
|
|
359
333
|
goal: input.goal,
|
|
360
334
|
goalState: input.state,
|
|
361
335
|
nextEvent: singleResult.result,
|
|
362
|
-
episodeId: agent.episodeId,
|
|
336
|
+
episodeId: input.episodeId ?? agent.episodeId,
|
|
363
337
|
timestamp: Date.now(),
|
|
364
338
|
paths: [
|
|
365
339
|
{
|
|
@@ -518,7 +492,6 @@ function createAgent({
|
|
|
518
492
|
});
|
|
519
493
|
}
|
|
520
494
|
var Agent = class extends Actor {
|
|
521
|
-
// todo
|
|
522
495
|
constructor({
|
|
523
496
|
logic = agentLogic,
|
|
524
497
|
id,
|
|
@@ -578,7 +551,7 @@ var Agent = class extends Actor {
|
|
|
578
551
|
comment: feedbackInput.comment ?? void 0,
|
|
579
552
|
attributes: { ...feedbackInput.attributes },
|
|
580
553
|
timestamp: feedbackInput.timestamp ?? Date.now(),
|
|
581
|
-
episodeId: this.episodeId
|
|
554
|
+
episodeId: feedbackInput.episodeId ?? this.episodeId
|
|
582
555
|
};
|
|
583
556
|
this.send({
|
|
584
557
|
type: "agent.feedback",
|
|
@@ -599,9 +572,12 @@ var Agent = class extends Actor {
|
|
|
599
572
|
event,
|
|
600
573
|
state,
|
|
601
574
|
id: observationInput.id ?? randomId(),
|
|
602
|
-
episodeId: this.episodeId,
|
|
575
|
+
episodeId: observationInput.episodeId ?? this.episodeId,
|
|
603
576
|
timestamp: observationInput.timestamp ?? Date.now(),
|
|
604
|
-
|
|
577
|
+
decisionId: observationInput.decisionId
|
|
578
|
+
// machineHash: observationInput.machine
|
|
579
|
+
// ? getMachineHash(observationInput.machine)
|
|
580
|
+
// : undefined,
|
|
605
581
|
};
|
|
606
582
|
this.send({
|
|
607
583
|
type: "agent.observe",
|
|
@@ -660,19 +636,18 @@ var Agent = class extends Actor {
|
|
|
660
636
|
event: inspEvent.event,
|
|
661
637
|
prevState,
|
|
662
638
|
state: inspEvent.snapshot,
|
|
663
|
-
|
|
664
|
-
|
|
639
|
+
goal: decision?.goal,
|
|
640
|
+
decisionId
|
|
665
641
|
};
|
|
666
642
|
await handleObservation(observationInput);
|
|
667
643
|
}
|
|
668
644
|
}) : void 0;
|
|
669
645
|
if (actorRef._processingStatus === 1) {
|
|
670
646
|
handleObservation({
|
|
647
|
+
decisionId: void 0,
|
|
671
648
|
prevState: void 0,
|
|
672
649
|
event: void 0,
|
|
673
|
-
state: actorRef.getSnapshot()
|
|
674
|
-
machine: actorRef.src,
|
|
675
|
-
goal: void 0
|
|
650
|
+
state: actorRef.getSnapshot()
|
|
676
651
|
});
|
|
677
652
|
}
|
|
678
653
|
return {
|
|
@@ -693,10 +668,10 @@ var Agent = class extends Actor {
|
|
|
693
668
|
const decisionId = inspEvent.event["_decision"];
|
|
694
669
|
const decision = decisionId ? this.getDecisions().find((d) => d.id === decisionId) : void 0;
|
|
695
670
|
const observationInput = {
|
|
671
|
+
decisionId,
|
|
696
672
|
event: inspEvent.event,
|
|
697
673
|
prevState,
|
|
698
674
|
state: inspEvent.snapshot,
|
|
699
|
-
machine: actorRef.src,
|
|
700
675
|
goal: decision?.goal
|
|
701
676
|
};
|
|
702
677
|
prevState = observationInput.state;
|
|
@@ -720,8 +695,8 @@ var Agent = class extends Actor {
|
|
|
720
695
|
* - The `machine` (e.g. a state machine) that specifies what can happen next
|
|
721
696
|
* - Additional `context`
|
|
722
697
|
*/
|
|
723
|
-
async decide(
|
|
724
|
-
return agentDecide(this,
|
|
698
|
+
async decide(input) {
|
|
699
|
+
return agentDecide(this, input);
|
|
725
700
|
}
|
|
726
701
|
};
|
|
727
702
|
export {
|
|
@@ -80,7 +80,7 @@ Achieve the goal. Consider both exploring unknown actions (high exploration_valu
|
|
|
80
80
|
|
|
81
81
|
if (decision?.nextEvent?.type === 'submit') {
|
|
82
82
|
const observation = await agent.addObservation({
|
|
83
|
-
|
|
83
|
+
decisionId: decision.id,
|
|
84
84
|
prevState: { value: 'editing' },
|
|
85
85
|
event: { type: 'submit' },
|
|
86
86
|
state: { value: 'editing' },
|
|
@@ -96,7 +96,7 @@ Achieve the goal. Consider both exploring unknown actions (high exploration_valu
|
|
|
96
96
|
status = 'submitted';
|
|
97
97
|
|
|
98
98
|
await agent.addObservation({
|
|
99
|
-
|
|
99
|
+
decisionId: decision.id,
|
|
100
100
|
prevState: { value: 'editing' },
|
|
101
101
|
event: { type: 'pressEnter' },
|
|
102
102
|
state: { value: 'submitted' },
|
package/package.json
CHANGED
package/src/agent.test.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { test, expect, vi } from 'vitest';
|
|
2
|
-
import { createAgent, TypesFromAgent } from './';
|
|
2
|
+
import { AgentDecision, createAgent, TypesFromAgent } from './';
|
|
3
3
|
import { createActor, createMachine } from 'xstate';
|
|
4
4
|
import { LanguageModelV1CallOptions } from 'ai';
|
|
5
5
|
import { z } from 'zod';
|
|
@@ -66,15 +66,30 @@ test('agent.addMessage() adds to message history', () => {
|
|
|
66
66
|
test('agent.addFeedback() adds to feedback', () => {
|
|
67
67
|
const agent = createAgent({
|
|
68
68
|
id: 'test',
|
|
69
|
-
events: {
|
|
69
|
+
events: {
|
|
70
|
+
play: z.object({
|
|
71
|
+
position: z.number(),
|
|
72
|
+
}),
|
|
73
|
+
},
|
|
70
74
|
model: {} as any,
|
|
71
75
|
});
|
|
72
76
|
|
|
77
|
+
const decision: AgentDecision<typeof agent> = {
|
|
78
|
+
goal: 'Win the game',
|
|
79
|
+
episodeId: agent.episodeId,
|
|
80
|
+
goalState: { value: 'won' },
|
|
81
|
+
id: 'decision-1',
|
|
82
|
+
nextEvent: { type: 'play', position: 3 },
|
|
83
|
+
paths: [],
|
|
84
|
+
strategy: 'simple',
|
|
85
|
+
timestamp: Date.now(),
|
|
86
|
+
};
|
|
87
|
+
|
|
73
88
|
const obs = agent.addObservation({
|
|
89
|
+
decisionId: decision.id,
|
|
74
90
|
prevState: { value: 'playing' },
|
|
75
|
-
state: { value: 'lost' },
|
|
76
91
|
event: { type: 'play', position: 3 },
|
|
77
|
-
|
|
92
|
+
state: { value: 'lost' },
|
|
78
93
|
});
|
|
79
94
|
|
|
80
95
|
const feedback = agent.addFeedback({
|
|
@@ -167,7 +182,6 @@ test('agent.addObservation() adds to observations with machine hash', () => {
|
|
|
167
182
|
prevState: { value: 'playing', context: {} },
|
|
168
183
|
event: { type: 'play', position: 3 },
|
|
169
184
|
state: { value: 'lost', context: {} },
|
|
170
|
-
machine,
|
|
171
185
|
goal: 'Win the game',
|
|
172
186
|
});
|
|
173
187
|
|
|
@@ -178,7 +192,6 @@ test('agent.addObservation() adds to observations with machine hash', () => {
|
|
|
178
192
|
prevState: { value: 'playing', context: {} },
|
|
179
193
|
event: { type: 'play', position: 3 },
|
|
180
194
|
state: { value: 'lost', context: {} },
|
|
181
|
-
machineHash: expect.any(String),
|
|
182
195
|
episodeId: expect.any(String),
|
|
183
196
|
timestamp: expect.any(Number),
|
|
184
197
|
})
|
|
@@ -503,7 +516,6 @@ test('agent.observe() adds observations from actor snapshots', () => {
|
|
|
503
516
|
expect(agent.getObservations()).toContainEqual(
|
|
504
517
|
expect.objectContaining({
|
|
505
518
|
state: expect.objectContaining({ value: 'idle' }),
|
|
506
|
-
machineHash: expect.any(String),
|
|
507
519
|
})
|
|
508
520
|
);
|
|
509
521
|
|
|
@@ -512,9 +524,95 @@ test('agent.observe() adds observations from actor snapshots', () => {
|
|
|
512
524
|
prevState: expect.objectContaining({ value: 'idle' }),
|
|
513
525
|
event: { type: 'START' },
|
|
514
526
|
state: expect.objectContaining({ value: 'running' }),
|
|
515
|
-
machineHash: expect.any(String),
|
|
516
527
|
})
|
|
517
528
|
);
|
|
518
529
|
|
|
519
530
|
subscription.unsubscribe();
|
|
520
531
|
});
|
|
532
|
+
|
|
533
|
+
test('agent.addObservation() accepts custom episodeId', () => {
|
|
534
|
+
const agent = createAgent({
|
|
535
|
+
id: 'test',
|
|
536
|
+
events: {},
|
|
537
|
+
model: {} as any,
|
|
538
|
+
});
|
|
539
|
+
|
|
540
|
+
const customEpisodeId = 'custom-episode-123';
|
|
541
|
+
const observation = agent.addObservation({
|
|
542
|
+
state: { value: 'playing' },
|
|
543
|
+
goal: 'Win the game',
|
|
544
|
+
episodeId: customEpisodeId,
|
|
545
|
+
});
|
|
546
|
+
|
|
547
|
+
expect(observation.episodeId).toEqual(customEpisodeId);
|
|
548
|
+
expect(agent.getObservations()).toContainEqual(
|
|
549
|
+
expect.objectContaining({
|
|
550
|
+
episodeId: customEpisodeId,
|
|
551
|
+
})
|
|
552
|
+
);
|
|
553
|
+
});
|
|
554
|
+
|
|
555
|
+
test('agent.addFeedback() accepts custom episodeId', () => {
|
|
556
|
+
const agent = createAgent({
|
|
557
|
+
id: 'test',
|
|
558
|
+
events: {},
|
|
559
|
+
model: {} as any,
|
|
560
|
+
});
|
|
561
|
+
|
|
562
|
+
const customEpisodeId = 'custom-episode-123';
|
|
563
|
+
const feedback = agent.addFeedback({
|
|
564
|
+
score: 1,
|
|
565
|
+
observationId: 'obs-1',
|
|
566
|
+
episodeId: customEpisodeId,
|
|
567
|
+
});
|
|
568
|
+
|
|
569
|
+
expect(feedback.episodeId).toEqual(customEpisodeId);
|
|
570
|
+
expect(agent.getFeedback()).toContainEqual(
|
|
571
|
+
expect.objectContaining({
|
|
572
|
+
episodeId: customEpisodeId,
|
|
573
|
+
})
|
|
574
|
+
);
|
|
575
|
+
});
|
|
576
|
+
|
|
577
|
+
test('agent.addObservation() accepts decisionId', () => {
|
|
578
|
+
const agent = createAgent({
|
|
579
|
+
id: 'test',
|
|
580
|
+
events: {},
|
|
581
|
+
model: {} as any,
|
|
582
|
+
});
|
|
583
|
+
|
|
584
|
+
const decisionId = 'decision-123';
|
|
585
|
+
const observation = agent.addObservation({
|
|
586
|
+
state: { value: 'playing' },
|
|
587
|
+
goal: 'Win the game',
|
|
588
|
+
decisionId,
|
|
589
|
+
});
|
|
590
|
+
|
|
591
|
+
expect(observation.decisionId).toEqual(decisionId);
|
|
592
|
+
expect(agent.getObservations()).toContainEqual(
|
|
593
|
+
expect.objectContaining({
|
|
594
|
+
decisionId,
|
|
595
|
+
})
|
|
596
|
+
);
|
|
597
|
+
});
|
|
598
|
+
|
|
599
|
+
test('agent.addFeedback() accepts decisionId', () => {
|
|
600
|
+
const agent = createAgent({
|
|
601
|
+
id: 'test',
|
|
602
|
+
events: {},
|
|
603
|
+
model: {} as any,
|
|
604
|
+
});
|
|
605
|
+
|
|
606
|
+
const decisionId = 'decision-123';
|
|
607
|
+
const feedback = agent.addFeedback({
|
|
608
|
+
score: 1,
|
|
609
|
+
decisionId,
|
|
610
|
+
});
|
|
611
|
+
|
|
612
|
+
expect(feedback.decisionId).toEqual(decisionId);
|
|
613
|
+
expect(agent.getFeedback()).toContainEqual(
|
|
614
|
+
expect.objectContaining({
|
|
615
|
+
decisionId,
|
|
616
|
+
})
|
|
617
|
+
);
|
|
618
|
+
});
|