@statelyai/agent 2.0.0-alpha.17 → 2.0.0-alpha.19
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/dist/ai-sdk.cjs +4 -2
- package/dist/ai-sdk.d.cts +1 -1
- package/dist/ai-sdk.d.mts +1 -1
- package/dist/ai-sdk.mjs +3 -2
- package/dist/{decision-C11xuud2.mjs → decision-DsIkEuHz.mjs} +48 -28
- package/dist/{decision-DnQCQPew.cjs → decision-t26zsnSR.cjs} +64 -43
- package/dist/{event-log-store-CQJq8_v4.d.cts → event-log-store-Bz7HDBkE.d.cts} +11 -12
- package/dist/{event-log-store-B-1fcfkT.mjs → event-log-store-DmIDosD6.mjs} +22 -14
- package/dist/{event-log-store-yquOV1TX.cjs → event-log-store-a_TKy1gk.cjs} +22 -14
- package/dist/{event-log-store-BrC9Q1xW.d.mts → event-log-store-hrA1vqtN.d.mts} +11 -12
- package/dist/index.cjs +266 -109
- package/dist/index.d.cts +148 -80
- package/dist/index.d.mts +148 -80
- package/dist/index.mjs +262 -107
- package/dist/machines.cjs +13 -17
- package/dist/machines.d.cts +14 -17
- package/dist/machines.d.mts +14 -17
- package/dist/machines.mjs +13 -17
- package/dist/otel.cjs +1 -0
- package/dist/otel.d.cts +1 -1
- package/dist/otel.d.mts +1 -1
- package/dist/{run-agent-BxjGaVpL.d.cts → run-agent--4bbms-D.d.cts} +121 -48
- package/dist/{run-agent-COHoCgQd.d.mts → run-agent-CwmzAZwj.d.mts} +121 -48
- package/dist/{setup-agent-D_EyJ0Ik.cjs → setup-agent-BFA4VKpN.cjs} +51 -33
- package/dist/{setup-agent-CTg57Pa4.mjs → setup-agent-CPFPN06s.mjs} +45 -28
- package/dist/sqlite.cjs +3 -9
- package/dist/sqlite.d.cts +1 -1
- package/dist/sqlite.d.mts +1 -1
- package/dist/sqlite.mjs +3 -9
- package/dist/{text-logic-BFX5q7fM.d.cts → text-logic-Cavva1W6.d.cts} +25 -9
- package/dist/{text-logic-DQW8_DWW.d.mts → text-logic-Er5KkTX6.d.mts} +25 -9
- package/dist/validate.cjs +436 -0
- package/dist/validate.d.cts +31 -0
- package/dist/validate.d.mts +31 -0
- package/dist/validate.mjs +411 -0
- package/package.json +15 -1
- package/schemas/agent-workflow.json +2 -2
- package/skills/generate-machine/SKILL.md +12 -14
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
import Ajv2020 from "ajv/dist/2020.js";
|
|
2
|
+
//#region schemas/agent-workflow.json
|
|
3
|
+
var agent_workflow_default = {
|
|
4
|
+
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
5
|
+
$id: "https://stately.ai/schemas/agent-workflow.json",
|
|
6
|
+
title: "Stately Agent Workflow Definition",
|
|
7
|
+
description: "Static, declarative agent workflow definition that can be lowered to a setupAgent(...) XState machine.",
|
|
8
|
+
type: "object",
|
|
9
|
+
required: ["initial", "states"],
|
|
10
|
+
properties: {
|
|
11
|
+
"$schema": {
|
|
12
|
+
"description": "JSON Schema reference an editor attaches to the config file. Ignored by the lowering.",
|
|
13
|
+
"type": "string"
|
|
14
|
+
},
|
|
15
|
+
"key": {
|
|
16
|
+
"description": "Stable workflow key used by tools, storage, and visual editors.",
|
|
17
|
+
"type": "string",
|
|
18
|
+
"minLength": 1
|
|
19
|
+
},
|
|
20
|
+
"id": {
|
|
21
|
+
"description": "Optional XState machine id.",
|
|
22
|
+
"type": "string",
|
|
23
|
+
"minLength": 1
|
|
24
|
+
},
|
|
25
|
+
"version": {
|
|
26
|
+
"description": "Definition version chosen by the author.",
|
|
27
|
+
"type": "string"
|
|
28
|
+
},
|
|
29
|
+
"description": { "type": "string" },
|
|
30
|
+
"schemas": { "$ref": "#/$defs/AgentSchemas" },
|
|
31
|
+
"context": {
|
|
32
|
+
"description": "Initial XState context. Values may be JSON literals or whole-string {{ }} expressions evaluated with machine input.",
|
|
33
|
+
"$ref": "#/$defs/ExpressionObject"
|
|
34
|
+
},
|
|
35
|
+
"requests": {
|
|
36
|
+
"description": "Named model requests that become typed invoke sources.",
|
|
37
|
+
"type": "object",
|
|
38
|
+
"propertyNames": { "$ref": "#/$defs/Identifier" },
|
|
39
|
+
"additionalProperties": { "$ref": "#/$defs/Request" },
|
|
40
|
+
"default": {}
|
|
41
|
+
},
|
|
42
|
+
"actors": {
|
|
43
|
+
"description": "Placeholder actor sources declared by key. JSON wires no execution; provide the logic via machine.provide({ actors }) after setupAgent.fromConfig(...).",
|
|
44
|
+
"type": "object",
|
|
45
|
+
"propertyNames": { "$ref": "#/$defs/Identifier" },
|
|
46
|
+
"additionalProperties": { "$ref": "#/$defs/Actor" },
|
|
47
|
+
"default": {}
|
|
48
|
+
},
|
|
49
|
+
"initial": {
|
|
50
|
+
"description": "Initial child state key.",
|
|
51
|
+
"type": "string"
|
|
52
|
+
},
|
|
53
|
+
"states": {
|
|
54
|
+
"description": "Root state nodes.",
|
|
55
|
+
"type": "object",
|
|
56
|
+
"minProperties": 1,
|
|
57
|
+
"propertyNames": { "$ref": "#/$defs/Identifier" },
|
|
58
|
+
"additionalProperties": { "$ref": "#/$defs/State" }
|
|
59
|
+
},
|
|
60
|
+
"idleTags": {
|
|
61
|
+
"description": "State tags that mark an intentional wait for an external event (a human approval, an inbound webhook, ...). Lowered by setupAgent.fromConfig(...) into a snapshot.hasTag(...) idle predicate so runAgent settles those states idle deterministically. Every listed tag must appear in some state's 'tags'.",
|
|
62
|
+
"type": "array",
|
|
63
|
+
"items": {
|
|
64
|
+
"type": "string",
|
|
65
|
+
"minLength": 1
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
"meta": { "$ref": "#/$defs/JsonObject" }
|
|
69
|
+
},
|
|
70
|
+
additionalProperties: false,
|
|
71
|
+
$defs: {
|
|
72
|
+
"Identifier": {
|
|
73
|
+
"type": "string",
|
|
74
|
+
"minLength": 1,
|
|
75
|
+
"pattern": "^[A-Za-z_$][A-Za-z0-9_$.-]*$"
|
|
76
|
+
},
|
|
77
|
+
"ExpressionString": {
|
|
78
|
+
"description": "Whole-string expression delimited by {{ }}.",
|
|
79
|
+
"type": "string",
|
|
80
|
+
"pattern": "^\\{\\{[\\s\\S]*\\}\\}$"
|
|
81
|
+
},
|
|
82
|
+
"TemplateString": {
|
|
83
|
+
"description": "String that may contain {{ }} template expressions. Escape literal delimiters according to the selected expression/template evaluator.",
|
|
84
|
+
"type": "string"
|
|
85
|
+
},
|
|
86
|
+
"JsonValue": { "anyOf": [
|
|
87
|
+
{ "type": "null" },
|
|
88
|
+
{ "type": "boolean" },
|
|
89
|
+
{ "type": "number" },
|
|
90
|
+
{ "type": "string" },
|
|
91
|
+
{
|
|
92
|
+
"type": "array",
|
|
93
|
+
"items": { "$ref": "#/$defs/JsonValue" }
|
|
94
|
+
},
|
|
95
|
+
{ "$ref": "#/$defs/JsonObject" }
|
|
96
|
+
] },
|
|
97
|
+
"JsonObject": {
|
|
98
|
+
"type": "object",
|
|
99
|
+
"propertyNames": { "type": "string" },
|
|
100
|
+
"additionalProperties": { "$ref": "#/$defs/JsonValue" }
|
|
101
|
+
},
|
|
102
|
+
"ExpressionValue": {
|
|
103
|
+
"description": "JSON value or whole-string {{ }} expression. Use this for typed values, not prompt templating.",
|
|
104
|
+
"anyOf": [
|
|
105
|
+
{ "$ref": "#/$defs/ExpressionString" },
|
|
106
|
+
{ "type": "null" },
|
|
107
|
+
{ "type": "boolean" },
|
|
108
|
+
{ "type": "number" },
|
|
109
|
+
{ "type": "string" },
|
|
110
|
+
{
|
|
111
|
+
"type": "array",
|
|
112
|
+
"items": { "$ref": "#/$defs/ExpressionValue" }
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
"type": "object",
|
|
116
|
+
"propertyNames": { "type": "string" },
|
|
117
|
+
"additionalProperties": { "$ref": "#/$defs/ExpressionValue" }
|
|
118
|
+
}
|
|
119
|
+
]
|
|
120
|
+
},
|
|
121
|
+
"ExpressionObject": {
|
|
122
|
+
"type": "object",
|
|
123
|
+
"propertyNames": { "type": "string" },
|
|
124
|
+
"additionalProperties": { "$ref": "#/$defs/ExpressionValue" }
|
|
125
|
+
},
|
|
126
|
+
"JsonSchema": {
|
|
127
|
+
"description": "JSON Schema object.",
|
|
128
|
+
"type": "object",
|
|
129
|
+
"propertyNames": { "type": "string" },
|
|
130
|
+
"additionalProperties": true
|
|
131
|
+
},
|
|
132
|
+
"AgentSchemas": {
|
|
133
|
+
"type": "object",
|
|
134
|
+
"properties": {
|
|
135
|
+
"input": { "$ref": "#/$defs/JsonSchema" },
|
|
136
|
+
"context": { "$ref": "#/$defs/JsonSchema" },
|
|
137
|
+
"events": {
|
|
138
|
+
"type": "object",
|
|
139
|
+
"propertyNames": { "$ref": "#/$defs/Identifier" },
|
|
140
|
+
"additionalProperties": { "$ref": "#/$defs/JsonSchema" }
|
|
141
|
+
},
|
|
142
|
+
"emitted": {
|
|
143
|
+
"type": "object",
|
|
144
|
+
"description": "Schemas for events emitted outward by emit actions, keyed by emitted event type.",
|
|
145
|
+
"propertyNames": { "$ref": "#/$defs/Identifier" },
|
|
146
|
+
"additionalProperties": { "$ref": "#/$defs/JsonSchema" }
|
|
147
|
+
},
|
|
148
|
+
"output": { "$ref": "#/$defs/JsonSchema" },
|
|
149
|
+
"meta": { "$ref": "#/$defs/JsonSchema" }
|
|
150
|
+
},
|
|
151
|
+
"additionalProperties": false
|
|
152
|
+
},
|
|
153
|
+
"Request": {
|
|
154
|
+
"type": "object",
|
|
155
|
+
"required": [
|
|
156
|
+
"model",
|
|
157
|
+
"input",
|
|
158
|
+
"output"
|
|
159
|
+
],
|
|
160
|
+
"properties": {
|
|
161
|
+
"mode": {
|
|
162
|
+
"type": "string",
|
|
163
|
+
"enum": ["generate", "stream"],
|
|
164
|
+
"default": "generate"
|
|
165
|
+
},
|
|
166
|
+
"description": { "type": "string" },
|
|
167
|
+
"model": { "$ref": "#/$defs/TemplateString" },
|
|
168
|
+
"system": { "$ref": "#/$defs/TemplateString" },
|
|
169
|
+
"prompt": { "$ref": "#/$defs/TemplateString" },
|
|
170
|
+
"messages": { "anyOf": [{ "$ref": "#/$defs/ExpressionString" }, {
|
|
171
|
+
"type": "array",
|
|
172
|
+
"items": { "$ref": "#/$defs/Message" }
|
|
173
|
+
}] },
|
|
174
|
+
"input": { "$ref": "#/$defs/JsonSchema" },
|
|
175
|
+
"output": { "$ref": "#/$defs/JsonSchema" },
|
|
176
|
+
"tools": {
|
|
177
|
+
"type": "object",
|
|
178
|
+
"propertyNames": { "$ref": "#/$defs/Identifier" },
|
|
179
|
+
"additionalProperties": { "$ref": "#/$defs/Tool" }
|
|
180
|
+
},
|
|
181
|
+
"toolChoice": {
|
|
182
|
+
"description": "Passed to the provider as-is; unlike other request fields it is NOT template-evaluated, so {{ }} expressions are not allowed here.",
|
|
183
|
+
"anyOf": [{
|
|
184
|
+
"type": "string",
|
|
185
|
+
"enum": [
|
|
186
|
+
"auto",
|
|
187
|
+
"none",
|
|
188
|
+
"required"
|
|
189
|
+
]
|
|
190
|
+
}, {
|
|
191
|
+
"type": "object",
|
|
192
|
+
"required": ["type", "name"],
|
|
193
|
+
"properties": {
|
|
194
|
+
"type": { "const": "tool" },
|
|
195
|
+
"name": { "$ref": "#/$defs/Identifier" }
|
|
196
|
+
},
|
|
197
|
+
"additionalProperties": false
|
|
198
|
+
}]
|
|
199
|
+
},
|
|
200
|
+
"reasoning": {
|
|
201
|
+
"description": "Opt into the structured-output envelope's `reasoning` field.",
|
|
202
|
+
"type": "boolean"
|
|
203
|
+
},
|
|
204
|
+
"temperature": { "$ref": "#/$defs/ExpressionValue" },
|
|
205
|
+
"maxOutputTokens": { "$ref": "#/$defs/ExpressionValue" },
|
|
206
|
+
"topP": { "$ref": "#/$defs/ExpressionValue" },
|
|
207
|
+
"topK": { "$ref": "#/$defs/ExpressionValue" },
|
|
208
|
+
"seed": { "$ref": "#/$defs/ExpressionValue" },
|
|
209
|
+
"stopSequences": { "anyOf": [{ "$ref": "#/$defs/ExpressionString" }, {
|
|
210
|
+
"type": "array",
|
|
211
|
+
"items": { "type": "string" }
|
|
212
|
+
}] },
|
|
213
|
+
"metadata": { "$ref": "#/$defs/ExpressionValue" }
|
|
214
|
+
},
|
|
215
|
+
"additionalProperties": false
|
|
216
|
+
},
|
|
217
|
+
"Message": {
|
|
218
|
+
"type": "object",
|
|
219
|
+
"required": ["role", "content"],
|
|
220
|
+
"properties": {
|
|
221
|
+
"role": { "$ref": "#/$defs/TemplateString" },
|
|
222
|
+
"content": { "$ref": "#/$defs/TemplateString" }
|
|
223
|
+
},
|
|
224
|
+
"additionalProperties": { "$ref": "#/$defs/ExpressionValue" }
|
|
225
|
+
},
|
|
226
|
+
"Actor": {
|
|
227
|
+
"description": "A placeholder actor source: schemas describe it for authors/editors; the implementation is provided by the host.",
|
|
228
|
+
"type": "object",
|
|
229
|
+
"properties": {
|
|
230
|
+
"description": { "type": "string" },
|
|
231
|
+
"input": { "$ref": "#/$defs/JsonSchema" },
|
|
232
|
+
"output": { "$ref": "#/$defs/JsonSchema" }
|
|
233
|
+
},
|
|
234
|
+
"additionalProperties": false
|
|
235
|
+
},
|
|
236
|
+
"Tool": {
|
|
237
|
+
"type": "object",
|
|
238
|
+
"properties": {
|
|
239
|
+
"description": { "type": "string" },
|
|
240
|
+
"inputSchema": { "$ref": "#/$defs/JsonSchema" },
|
|
241
|
+
"outputSchema": { "$ref": "#/$defs/JsonSchema" }
|
|
242
|
+
},
|
|
243
|
+
"additionalProperties": { "$ref": "#/$defs/JsonValue" }
|
|
244
|
+
},
|
|
245
|
+
"State": {
|
|
246
|
+
"type": "object",
|
|
247
|
+
"properties": {
|
|
248
|
+
"description": { "type": "string" },
|
|
249
|
+
"type": {
|
|
250
|
+
"type": "string",
|
|
251
|
+
"enum": [
|
|
252
|
+
"parallel",
|
|
253
|
+
"history",
|
|
254
|
+
"final",
|
|
255
|
+
"choice"
|
|
256
|
+
]
|
|
257
|
+
},
|
|
258
|
+
"initial": { "type": "string" },
|
|
259
|
+
"states": {
|
|
260
|
+
"type": "object",
|
|
261
|
+
"propertyNames": { "$ref": "#/$defs/Identifier" },
|
|
262
|
+
"additionalProperties": { "$ref": "#/$defs/State" }
|
|
263
|
+
},
|
|
264
|
+
"invoke": { "anyOf": [{ "$ref": "#/$defs/Invoke" }, {
|
|
265
|
+
"type": "array",
|
|
266
|
+
"items": { "$ref": "#/$defs/Invoke" }
|
|
267
|
+
}] },
|
|
268
|
+
"choice": {
|
|
269
|
+
"description": "Choice-state routing, equivalent to XState's type: 'choice' + choice transition function.",
|
|
270
|
+
"$ref": "#/$defs/TransitionOrArray"
|
|
271
|
+
},
|
|
272
|
+
"on": {
|
|
273
|
+
"type": "object",
|
|
274
|
+
"propertyNames": { "type": "string" },
|
|
275
|
+
"additionalProperties": { "$ref": "#/$defs/TransitionOrArray" }
|
|
276
|
+
},
|
|
277
|
+
"always": { "$ref": "#/$defs/TransitionOrArray" },
|
|
278
|
+
"onDone": { "$ref": "#/$defs/TransitionOrArray" },
|
|
279
|
+
"after": {
|
|
280
|
+
"type": "object",
|
|
281
|
+
"propertyNames": { "type": "string" },
|
|
282
|
+
"additionalProperties": { "$ref": "#/$defs/TransitionOrArray" }
|
|
283
|
+
},
|
|
284
|
+
"entry": { "$ref": "#/$defs/ActionOrArray" },
|
|
285
|
+
"exit": { "$ref": "#/$defs/ActionOrArray" },
|
|
286
|
+
"tags": {
|
|
287
|
+
"type": "array",
|
|
288
|
+
"items": { "type": "string" }
|
|
289
|
+
},
|
|
290
|
+
"output": { "$ref": "#/$defs/ExpressionValue" },
|
|
291
|
+
"meta": {
|
|
292
|
+
"description": "Static state metadata, passed through verbatim. Not template-evaluated.",
|
|
293
|
+
"$ref": "#/$defs/JsonObject"
|
|
294
|
+
}
|
|
295
|
+
},
|
|
296
|
+
"additionalProperties": false
|
|
297
|
+
},
|
|
298
|
+
"Invoke": {
|
|
299
|
+
"type": "object",
|
|
300
|
+
"required": ["src"],
|
|
301
|
+
"properties": {
|
|
302
|
+
"id": { "type": "string" },
|
|
303
|
+
"src": {
|
|
304
|
+
"description": "Actor source name. 'agent.decide' invokes are special: decision delivery is automatic (the chosen event is sent as soon as the model decides) and 'onDone' must be omitted — see the 'onDone' description.",
|
|
305
|
+
"$ref": "#/$defs/Identifier"
|
|
306
|
+
},
|
|
307
|
+
"input": { "$ref": "#/$defs/ExpressionValue" },
|
|
308
|
+
"onDone": {
|
|
309
|
+
"description": "Not valid on an 'agent.decide' invoke — the built-in lowering rejects it at setupAgent.fromConfig(...) time. A decision has no output value of its own (its output IS the chosen event), so delivery is automatic and not configurable from JSON. 'onError' (retries exhausted) still applies to 'agent.decide' invokes.",
|
|
310
|
+
"$ref": "#/$defs/TransitionOrArray"
|
|
311
|
+
},
|
|
312
|
+
"onError": { "$ref": "#/$defs/TransitionOrArray" }
|
|
313
|
+
},
|
|
314
|
+
"additionalProperties": false
|
|
315
|
+
},
|
|
316
|
+
"TransitionOrArray": { "anyOf": [{ "$ref": "#/$defs/Transition" }, {
|
|
317
|
+
"type": "array",
|
|
318
|
+
"items": { "$ref": "#/$defs/Transition" }
|
|
319
|
+
}] },
|
|
320
|
+
"Transition": {
|
|
321
|
+
"type": "object",
|
|
322
|
+
"properties": {
|
|
323
|
+
"target": { "anyOf": [{ "type": "string" }, {
|
|
324
|
+
"type": "array",
|
|
325
|
+
"items": { "type": "string" }
|
|
326
|
+
}] },
|
|
327
|
+
"guard": {
|
|
328
|
+
"description": "Either a whole-string {{ }} expression evaluated as truthy/falsy, or a named guard reference resolved against the `guards` passed to setupAgent.fromConfig(config, { guards }). Object guards ({ type, params }) are rejected by the lowering.",
|
|
329
|
+
"anyOf": [{ "$ref": "#/$defs/ExpressionString" }, { "$ref": "#/$defs/Identifier" }]
|
|
330
|
+
},
|
|
331
|
+
"assign": {
|
|
332
|
+
"description": "Context assignments applied when this transition is taken.",
|
|
333
|
+
"$ref": "#/$defs/ExpressionObject"
|
|
334
|
+
},
|
|
335
|
+
"actions": { "$ref": "#/$defs/ActionOrArray" },
|
|
336
|
+
"description": { "type": "string" },
|
|
337
|
+
"reenter": { "type": "boolean" },
|
|
338
|
+
"meta": {
|
|
339
|
+
"description": "Static transition metadata, passed through verbatim. Not template-evaluated.",
|
|
340
|
+
"$ref": "#/$defs/JsonObject"
|
|
341
|
+
}
|
|
342
|
+
},
|
|
343
|
+
"additionalProperties": false
|
|
344
|
+
},
|
|
345
|
+
"ActionOrArray": { "anyOf": [{ "$ref": "#/$defs/Action" }, {
|
|
346
|
+
"type": "array",
|
|
347
|
+
"items": { "$ref": "#/$defs/Action" }
|
|
348
|
+
}] },
|
|
349
|
+
"Action": {
|
|
350
|
+
"type": "object",
|
|
351
|
+
"properties": {
|
|
352
|
+
"type": { "type": "string" },
|
|
353
|
+
"params": { "$ref": "#/$defs/ExpressionValue" },
|
|
354
|
+
"assign": { "$ref": "#/$defs/ExpressionObject" },
|
|
355
|
+
"emit": {
|
|
356
|
+
"description": "Event emitted outward through runAgent's on handlers.",
|
|
357
|
+
"$ref": "#/$defs/ExpressionValue"
|
|
358
|
+
}
|
|
359
|
+
},
|
|
360
|
+
"anyOf": [
|
|
361
|
+
{ "required": ["type"] },
|
|
362
|
+
{ "required": ["assign"] },
|
|
363
|
+
{ "required": ["emit"] }
|
|
364
|
+
],
|
|
365
|
+
"additionalProperties": { "$ref": "#/$defs/ExpressionValue" }
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
};
|
|
369
|
+
//#endregion
|
|
370
|
+
//#region src/validate/index.ts
|
|
371
|
+
/**
|
|
372
|
+
* Schema validation for agent workflow configs.
|
|
373
|
+
*
|
|
374
|
+
* Lives behind the `@statelyai/agent/validate` subpath so the core package
|
|
375
|
+
* stays dependency-free. This module imports `ajv`, which is declared as an
|
|
376
|
+
* optional peer dependency.
|
|
377
|
+
*/
|
|
378
|
+
let compiledWorkflowValidator;
|
|
379
|
+
function getWorkflowValidator() {
|
|
380
|
+
if (!compiledWorkflowValidator) compiledWorkflowValidator = new Ajv2020({
|
|
381
|
+
strict: false,
|
|
382
|
+
allowUnionTypes: true,
|
|
383
|
+
allErrors: true
|
|
384
|
+
}).compile(agent_workflow_default);
|
|
385
|
+
return compiledWorkflowValidator;
|
|
386
|
+
}
|
|
387
|
+
/**
|
|
388
|
+
* Validates a value against the shipped `schemas/agent-workflow.json` before
|
|
389
|
+
* you hand it to `setupAgent(...).fromConfig(...)`. Returns diagnostics rather
|
|
390
|
+
* than throwing; `valid: true` means the config is structurally sound (it does
|
|
391
|
+
* not check that named guards/actions/actors are implemented, which
|
|
392
|
+
* `fromConfig` does). The compiled validator is cached across calls.
|
|
393
|
+
*/
|
|
394
|
+
function validateAgentConfig(config) {
|
|
395
|
+
const validate = getWorkflowValidator();
|
|
396
|
+
if (validate(config)) return {
|
|
397
|
+
valid: true,
|
|
398
|
+
errors: []
|
|
399
|
+
};
|
|
400
|
+
return {
|
|
401
|
+
valid: false,
|
|
402
|
+
errors: (validate.errors ?? []).map((error) => ({
|
|
403
|
+
severity: "error",
|
|
404
|
+
path: error.instancePath || "/",
|
|
405
|
+
message: error.message ?? "is invalid",
|
|
406
|
+
keyword: error.keyword
|
|
407
|
+
}))
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
//#endregion
|
|
411
|
+
export { validateAgentConfig };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@statelyai/agent",
|
|
3
|
-
"version": "2.0.0-alpha.
|
|
3
|
+
"version": "2.0.0-alpha.19",
|
|
4
4
|
"description": "Make invalid agent actions impossible. Agent logic as state machines: deterministic, inspectable, resumable, runs anywhere.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agent",
|
|
@@ -68,6 +68,16 @@
|
|
|
68
68
|
"default": "./dist/otel.cjs"
|
|
69
69
|
}
|
|
70
70
|
},
|
|
71
|
+
"./validate": {
|
|
72
|
+
"import": {
|
|
73
|
+
"types": "./dist/validate.d.mts",
|
|
74
|
+
"default": "./dist/validate.mjs"
|
|
75
|
+
},
|
|
76
|
+
"require": {
|
|
77
|
+
"types": "./dist/validate.d.cts",
|
|
78
|
+
"default": "./dist/validate.cjs"
|
|
79
|
+
}
|
|
80
|
+
},
|
|
71
81
|
"./sqlite": {
|
|
72
82
|
"import": {
|
|
73
83
|
"types": "./dist/sqlite.d.mts",
|
|
@@ -127,6 +137,7 @@
|
|
|
127
137
|
"peerDependencies": {
|
|
128
138
|
"@opentelemetry/api": "^1",
|
|
129
139
|
"ai": "^6.0.67",
|
|
140
|
+
"ajv": "^8.20.0",
|
|
130
141
|
"xstate": ">=6.0.0-alpha.25 <6.0.0"
|
|
131
142
|
},
|
|
132
143
|
"peerDependenciesMeta": {
|
|
@@ -135,6 +146,9 @@
|
|
|
135
146
|
},
|
|
136
147
|
"ai": {
|
|
137
148
|
"optional": true
|
|
149
|
+
},
|
|
150
|
+
"ajv": {
|
|
151
|
+
"optional": true
|
|
138
152
|
}
|
|
139
153
|
},
|
|
140
154
|
"engines": {
|
|
@@ -71,8 +71,8 @@
|
|
|
71
71
|
"$ref": "#/$defs/State"
|
|
72
72
|
}
|
|
73
73
|
},
|
|
74
|
-
"
|
|
75
|
-
"description": "State tags that mark an intentional wait for an external event (a human approval, an inbound webhook, ...). Lowered by setupAgent.fromConfig(...) into a snapshot.hasTag(...)
|
|
74
|
+
"idleTags": {
|
|
75
|
+
"description": "State tags that mark an intentional wait for an external event (a human approval, an inbound webhook, ...). Lowered by setupAgent.fromConfig(...) into a snapshot.hasTag(...) idle predicate so runAgent settles those states idle deterministically. Every listed tag must appear in some state's 'tags'.",
|
|
76
76
|
"type": "array",
|
|
77
77
|
"items": {
|
|
78
78
|
"type": "string",
|
|
@@ -8,7 +8,7 @@ description: Author a @statelyai/agent workflow as JSON and check it before it r
|
|
|
8
8
|
An agent machine is data. You author a JSON `AgentWorkflowConfig`, then run it through gates that all work with no API key: Ajv → `fromConfig` → lint → simulate. Do not hand back a config that has not passed all four.
|
|
9
9
|
|
|
10
10
|
```
|
|
11
|
-
author → validate (
|
|
11
|
+
author → validate (validateAgentConfig) → lower (fromConfig) → lint (lintAgentMachine) → simulate → hand back
|
|
12
12
|
```
|
|
13
13
|
|
|
14
14
|
## 1. Read the schema
|
|
@@ -132,28 +132,26 @@ Reference config — decision, text request, idle human step, one final state:
|
|
|
132
132
|
}
|
|
133
133
|
```
|
|
134
134
|
|
|
135
|
-
## 3. Validate with
|
|
135
|
+
## 3. Validate with `validateAgentConfig`
|
|
136
136
|
|
|
137
|
-
|
|
137
|
+
`validateAgentConfig` from `@statelyai/agent/validate` checks a candidate against the shipped workflow schema with Ajv 2020 built in. It needs `ajv` installed (an optional peer of the package). Run it before anything else touches the config.
|
|
138
138
|
|
|
139
139
|
```ts
|
|
140
|
-
import
|
|
141
|
-
import workflowSchema from "@statelyai/agent/agent-workflow.json";
|
|
140
|
+
import { validateAgentConfig } from "@statelyai/agent/validate";
|
|
142
141
|
import type { AgentWorkflowConfig } from "@statelyai/agent";
|
|
143
142
|
|
|
144
|
-
const validateWorkflow = new Ajv2020({ strict: false }).compile(workflowSchema);
|
|
145
|
-
|
|
146
143
|
function validateGeneratedConfig(candidate: unknown): AgentWorkflowConfig {
|
|
147
|
-
|
|
144
|
+
const result = validateAgentConfig(candidate);
|
|
145
|
+
if (result.valid) return candidate as AgentWorkflowConfig;
|
|
148
146
|
throw new Error(
|
|
149
|
-
|
|
150
|
-
.map((error) => `${error.
|
|
147
|
+
result.errors
|
|
148
|
+
.map((error) => `${error.path || "(root)"} ${error.message}`)
|
|
151
149
|
.join("\n"),
|
|
152
150
|
);
|
|
153
151
|
}
|
|
154
152
|
```
|
|
155
153
|
|
|
156
|
-
|
|
154
|
+
Each error carries a JSON Pointer `path`, so a repair prompt can name the exact bad field.
|
|
157
155
|
|
|
158
156
|
## 4. Lower with `fromConfig`
|
|
159
157
|
|
|
@@ -193,10 +191,10 @@ Lowering is itself a gate: it throws on an unresolved named guard/action and on
|
|
|
193
191
|
## 5. Lint
|
|
194
192
|
|
|
195
193
|
```ts
|
|
196
|
-
import {
|
|
194
|
+
import { lintAgentMachine } from "@statelyai/agent";
|
|
197
195
|
|
|
198
196
|
const diagnostics = lintAgentMachine(machine);
|
|
199
|
-
|
|
197
|
+
lintAgentMachine(machine, { throw: true }); // throws AgentLintError on error-severity findings
|
|
200
198
|
```
|
|
201
199
|
|
|
202
200
|
Every check applies to config-built machines, reachability included — the lowering keeps the config's transition targets, so `unreachable-state` and `missing-final` read the real graph. Do not disable checks.
|
|
@@ -224,7 +222,7 @@ Derive the script from the config rather than guessing: take the first entry of
|
|
|
224
222
|
|
|
225
223
|
- `'exhausted'` → the machine loops. Reject it.
|
|
226
224
|
- `'idle'` → it stopped at a human step. Expected when the config has one.
|
|
227
|
-
- To cover every branch instead of one path, use `explorePaths` / `canReach
|
|
225
|
+
- To cover every branch instead of one path, use `explorePaths` / `canReach` (its result is `{ reachable, witness }`).
|
|
228
226
|
|
|
229
227
|
## 7. Repair loop
|
|
230
228
|
|