@openexpertise/schema 0.1.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/LICENSE +21 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/parser.d.ts +8 -0
- package/dist/parser.d.ts.map +1 -0
- package/dist/parser.js +25 -0
- package/dist/parser.js.map +1 -0
- package/dist/schemas/experience.schema.json +260 -0
- package/dist/types.d.ts +170 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/dist/validator.d.ts +7 -0
- package/dist/validator.d.ts.map +1 -0
- package/dist/validator.js +60 -0
- package/dist/validator.js.map +1 -0
- package/package.json +53 -0
- package/src/schemas/experience.schema.json +260 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 OpenExpertise
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAC1B,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AACjD,OAAO,EAAE,sBAAsB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAC1B,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AACjD,OAAO,EAAE,sBAAsB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA"}
|
package/dist/parser.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ExperienceSpec } from './types.js';
|
|
2
|
+
export declare class ParseError extends Error {
|
|
3
|
+
readonly line?: number | undefined;
|
|
4
|
+
readonly column?: number | undefined;
|
|
5
|
+
constructor(message: string, line?: number | undefined, column?: number | undefined);
|
|
6
|
+
}
|
|
7
|
+
export declare function parseExperienceYaml(source: string): ExperienceSpec;
|
|
8
|
+
//# sourceMappingURL=parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAEhD,qBAAa,UAAW,SAAQ,KAAK;aAGjB,IAAI,CAAC,EAAE,MAAM;aACb,MAAM,CAAC,EAAE,MAAM;gBAF/B,OAAO,EAAE,MAAM,EACC,IAAI,CAAC,EAAE,MAAM,YAAA,EACb,MAAM,CAAC,EAAE,MAAM,YAAA;CAKlC;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,CAgBlE"}
|
package/dist/parser.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { parseDocument } from 'yaml';
|
|
2
|
+
export class ParseError extends Error {
|
|
3
|
+
line;
|
|
4
|
+
column;
|
|
5
|
+
constructor(message, line, column) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.line = line;
|
|
8
|
+
this.column = column;
|
|
9
|
+
this.name = 'ParseError';
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export function parseExperienceYaml(source) {
|
|
13
|
+
const doc = parseDocument(source, { prettyErrors: true });
|
|
14
|
+
if (doc.errors.length > 0) {
|
|
15
|
+
const first = doc.errors[0];
|
|
16
|
+
const pos = first.linePos?.[0];
|
|
17
|
+
throw new ParseError(`YAML parse error at line ${pos?.line ?? '?'}, column ${pos?.col ?? '?'}: ${first.message}`, pos?.line, pos?.col);
|
|
18
|
+
}
|
|
19
|
+
const parsed = doc.toJS();
|
|
20
|
+
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
|
|
21
|
+
throw new ParseError('experience.yaml must be a YAML mapping at the top level');
|
|
22
|
+
}
|
|
23
|
+
return parsed;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parser.js","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAa,MAAM,MAAM,CAAA;AAG/C,MAAM,OAAO,UAAW,SAAQ,KAAK;IAGjB;IACA;IAHlB,YACE,OAAe,EACC,IAAa,EACb,MAAe;QAE/B,KAAK,CAAC,OAAO,CAAC,CAAA;QAHE,SAAI,GAAJ,IAAI,CAAS;QACb,WAAM,GAAN,MAAM,CAAS;QAG/B,IAAI,CAAC,IAAI,GAAG,YAAY,CAAA;IAC1B,CAAC;CACF;AAED,MAAM,UAAU,mBAAmB,CAAC,MAAc;IAChD,MAAM,GAAG,GAAG,aAAa,CAAC,MAAM,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAA;IACzD,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,MAAM,KAAK,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAc,CAAA;QACxC,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAA;QAC9B,MAAM,IAAI,UAAU,CAClB,4BAA4B,GAAG,EAAE,IAAI,IAAI,GAAG,YAAY,GAAG,EAAE,GAAG,IAAI,GAAG,KAAK,KAAK,CAAC,OAAO,EAAE,EAC3F,GAAG,EAAE,IAAI,EACT,GAAG,EAAE,GAAG,CACT,CAAA;IACH,CAAC;IACD,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,EAAE,CAAA;IACzB,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3E,MAAM,IAAI,UAAU,CAAC,yDAAyD,CAAC,CAAA;IACjF,CAAC;IACD,OAAO,MAAwB,CAAA;AACjC,CAAC"}
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://openexpertise.dev/schemas/experience-v0.1.0.json",
|
|
4
|
+
"title": "ExperienceSpec",
|
|
5
|
+
"_comment": "TODO Plan 2: tighten node oneOf variants with additionalProperties: false so typos like 'impl_path' don't pass validation and fail later at runtime.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["name", "version", "state", "graph"],
|
|
8
|
+
"additionalProperties": false,
|
|
9
|
+
"properties": {
|
|
10
|
+
"name": { "type": "string", "minLength": 1 },
|
|
11
|
+
"description": { "type": "string" },
|
|
12
|
+
"version": { "type": "string", "pattern": "^\\d+\\.\\d+\\.\\d+$" },
|
|
13
|
+
"state": {
|
|
14
|
+
"type": "object",
|
|
15
|
+
"required": ["schema"],
|
|
16
|
+
"additionalProperties": false,
|
|
17
|
+
"properties": {
|
|
18
|
+
"schema": {
|
|
19
|
+
"type": "object",
|
|
20
|
+
"additionalProperties": { "$ref": "#/$defs/stateField" }
|
|
21
|
+
},
|
|
22
|
+
"store": { "type": "string" }
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"phases": {
|
|
26
|
+
"type": "array",
|
|
27
|
+
"items": {
|
|
28
|
+
"type": "object",
|
|
29
|
+
"required": ["id"],
|
|
30
|
+
"additionalProperties": false,
|
|
31
|
+
"properties": {
|
|
32
|
+
"id": { "type": "string" },
|
|
33
|
+
"title": { "type": "string" }
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"graph": {
|
|
38
|
+
"type": "object",
|
|
39
|
+
"required": ["nodes", "edges"],
|
|
40
|
+
"additionalProperties": false,
|
|
41
|
+
"properties": {
|
|
42
|
+
"nodes": {
|
|
43
|
+
"type": "array",
|
|
44
|
+
"minItems": 1,
|
|
45
|
+
"items": { "$ref": "#/$defs/node" }
|
|
46
|
+
},
|
|
47
|
+
"edges": {
|
|
48
|
+
"type": "array",
|
|
49
|
+
"items": { "$ref": "#/$defs/edge" }
|
|
50
|
+
},
|
|
51
|
+
"pipelines": {
|
|
52
|
+
"type": "array",
|
|
53
|
+
"items": {
|
|
54
|
+
"type": "object",
|
|
55
|
+
"required": ["id", "items", "stages"],
|
|
56
|
+
"additionalProperties": false,
|
|
57
|
+
"properties": {
|
|
58
|
+
"id": { "type": "string" },
|
|
59
|
+
"items": { "type": "string" },
|
|
60
|
+
"stages": { "type": "array", "items": { "type": "string" }, "minItems": 1 },
|
|
61
|
+
"phase": { "type": "string" }
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
"loops": {
|
|
66
|
+
"type": "array",
|
|
67
|
+
"items": {
|
|
68
|
+
"type": "object",
|
|
69
|
+
"required": ["id", "body"],
|
|
70
|
+
"additionalProperties": false,
|
|
71
|
+
"properties": {
|
|
72
|
+
"id": { "type": "string" },
|
|
73
|
+
"body": { "type": "string" },
|
|
74
|
+
"until": { "type": "string" },
|
|
75
|
+
"max_iters": { "type": "integer", "minimum": 1 },
|
|
76
|
+
"budget": { "type": "integer", "minimum": 0 },
|
|
77
|
+
"phase": { "type": "string" }
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
"runtime": {
|
|
84
|
+
"type": "object",
|
|
85
|
+
"additionalProperties": false,
|
|
86
|
+
"properties": {
|
|
87
|
+
"concurrency": { "type": "integer", "minimum": 1 }
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
"$defs": {
|
|
92
|
+
"stateField": {
|
|
93
|
+
"type": "object",
|
|
94
|
+
"additionalProperties": true,
|
|
95
|
+
"properties": {
|
|
96
|
+
"type": {
|
|
97
|
+
"type": "string",
|
|
98
|
+
"enum": ["string", "number", "boolean", "object", "array", "null"]
|
|
99
|
+
},
|
|
100
|
+
"description": { "type": "string" },
|
|
101
|
+
"merge": { "enum": ["array_append", "set_once", "last_wins"] }
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
"edge": {
|
|
105
|
+
"type": "object",
|
|
106
|
+
"required": ["from", "to"],
|
|
107
|
+
"additionalProperties": false,
|
|
108
|
+
"properties": {
|
|
109
|
+
"from": { "type": "string" },
|
|
110
|
+
"to": { "type": "string" },
|
|
111
|
+
"when": { "type": "string" }
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
"errorPolicy": {
|
|
115
|
+
"oneOf": [
|
|
116
|
+
{
|
|
117
|
+
"type": "object",
|
|
118
|
+
"required": ["policy"],
|
|
119
|
+
"properties": { "policy": { "const": "skip" } },
|
|
120
|
+
"additionalProperties": false
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
"type": "object",
|
|
124
|
+
"required": ["policy"],
|
|
125
|
+
"properties": { "policy": { "const": "fail_run" } },
|
|
126
|
+
"additionalProperties": false
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
"type": "object",
|
|
130
|
+
"required": ["policy", "attempts"],
|
|
131
|
+
"properties": {
|
|
132
|
+
"policy": { "const": "retry" },
|
|
133
|
+
"attempts": { "type": "integer", "minimum": 1, "maximum": 20 },
|
|
134
|
+
"backoff": { "enum": ["linear", "exponential"] },
|
|
135
|
+
"base_ms": { "type": "integer", "minimum": 0 }
|
|
136
|
+
},
|
|
137
|
+
"additionalProperties": false
|
|
138
|
+
}
|
|
139
|
+
]
|
|
140
|
+
},
|
|
141
|
+
"nodeBase": {
|
|
142
|
+
"type": "object",
|
|
143
|
+
"required": ["id", "kind"],
|
|
144
|
+
"properties": {
|
|
145
|
+
"id": { "type": "string", "minLength": 1, "pattern": "^[a-zA-Z_][a-zA-Z0-9_]*$" },
|
|
146
|
+
"phase": { "type": "string" },
|
|
147
|
+
"reads": { "type": "array", "items": { "type": "string" } },
|
|
148
|
+
"writes": { "type": "array", "items": { "type": "string" } },
|
|
149
|
+
"on_error": { "$ref": "#/$defs/errorPolicy" },
|
|
150
|
+
"for_each": {
|
|
151
|
+
"type": "object",
|
|
152
|
+
"required": ["source"],
|
|
153
|
+
"properties": {
|
|
154
|
+
"source": { "type": "string" },
|
|
155
|
+
"concurrency": { "type": "integer", "minimum": 1 }
|
|
156
|
+
},
|
|
157
|
+
"additionalProperties": false
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
},
|
|
161
|
+
"node": {
|
|
162
|
+
"oneOf": [
|
|
163
|
+
{
|
|
164
|
+
"allOf": [
|
|
165
|
+
{ "$ref": "#/$defs/nodeBase" },
|
|
166
|
+
{
|
|
167
|
+
"type": "object",
|
|
168
|
+
"required": ["impl"],
|
|
169
|
+
"properties": {
|
|
170
|
+
"kind": { "const": "tool" },
|
|
171
|
+
"impl": { "type": "string" },
|
|
172
|
+
"args": { "type": "object" }
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
]
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
"allOf": [
|
|
179
|
+
{ "$ref": "#/$defs/nodeBase" },
|
|
180
|
+
{
|
|
181
|
+
"type": "object",
|
|
182
|
+
"required": ["prompt"],
|
|
183
|
+
"properties": {
|
|
184
|
+
"kind": { "const": "agent" },
|
|
185
|
+
"prompt": { "type": "string" },
|
|
186
|
+
"model": { "type": "string" },
|
|
187
|
+
"schema": {},
|
|
188
|
+
"args": { "type": "object" }
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
]
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
"allOf": [
|
|
195
|
+
{ "$ref": "#/$defs/nodeBase" },
|
|
196
|
+
{
|
|
197
|
+
"type": "object",
|
|
198
|
+
"required": ["impl"],
|
|
199
|
+
"properties": {
|
|
200
|
+
"kind": { "const": "skill" },
|
|
201
|
+
"impl": { "type": "string" },
|
|
202
|
+
"inputs": { "type": "object" },
|
|
203
|
+
"model": { "type": "string" },
|
|
204
|
+
"schema": {}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
]
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
"allOf": [
|
|
211
|
+
{ "$ref": "#/$defs/nodeBase" },
|
|
212
|
+
{
|
|
213
|
+
"type": "object",
|
|
214
|
+
"required": ["source"],
|
|
215
|
+
"properties": {
|
|
216
|
+
"kind": { "const": "dataset" },
|
|
217
|
+
"source": { "type": "object" }
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
]
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
"allOf": [
|
|
224
|
+
{ "$ref": "#/$defs/nodeBase" },
|
|
225
|
+
{
|
|
226
|
+
"type": "object",
|
|
227
|
+
"required": ["impl"],
|
|
228
|
+
"properties": {
|
|
229
|
+
"kind": { "const": "experience" },
|
|
230
|
+
"impl": { "type": "string" },
|
|
231
|
+
"args": { "type": "object" },
|
|
232
|
+
"state_scope": { "enum": ["shared", "isolated"] }
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
]
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
"allOf": [
|
|
239
|
+
{ "$ref": "#/$defs/nodeBase" },
|
|
240
|
+
{
|
|
241
|
+
"type": "object",
|
|
242
|
+
"required": ["provider", "prompt"],
|
|
243
|
+
"properties": {
|
|
244
|
+
"kind": { "const": "cli-agent" },
|
|
245
|
+
"provider": { "enum": ["claude-code", "codex", "gemini"] },
|
|
246
|
+
"prompt": { "type": "string", "minLength": 1 },
|
|
247
|
+
"model": { "type": "string" },
|
|
248
|
+
"workdir": { "type": "string" },
|
|
249
|
+
"output_format": { "enum": ["text", "json"] },
|
|
250
|
+
"schema": {},
|
|
251
|
+
"timeout_ms": { "type": "integer", "minimum": 1000 },
|
|
252
|
+
"extra_args": { "type": "array", "items": { "type": "string" } }
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
]
|
|
256
|
+
}
|
|
257
|
+
]
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
export type NodeKind = 'agent' | 'skill' | 'tool' | 'dataset' | 'experience' | 'cli-agent';
|
|
2
|
+
export type MergeStrategy = 'array_append' | 'set_once' | 'last_wins';
|
|
3
|
+
export interface ForEachClause {
|
|
4
|
+
source: string;
|
|
5
|
+
concurrency?: number;
|
|
6
|
+
}
|
|
7
|
+
export interface PipelineGroupSpec {
|
|
8
|
+
id: string;
|
|
9
|
+
items: string;
|
|
10
|
+
stages: string[];
|
|
11
|
+
phase?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface LoopSpec {
|
|
14
|
+
id: string;
|
|
15
|
+
body: string;
|
|
16
|
+
until?: string;
|
|
17
|
+
max_iters?: number;
|
|
18
|
+
budget?: number;
|
|
19
|
+
phase?: string;
|
|
20
|
+
}
|
|
21
|
+
export type StateFieldSchema = {
|
|
22
|
+
type: 'string' | 'number' | 'boolean' | 'object' | 'array' | 'null';
|
|
23
|
+
description?: string;
|
|
24
|
+
items?: StateFieldSchema | {
|
|
25
|
+
$ref: string;
|
|
26
|
+
};
|
|
27
|
+
properties?: Record<string, StateFieldSchema>;
|
|
28
|
+
required?: string[];
|
|
29
|
+
merge?: MergeStrategy;
|
|
30
|
+
} | {
|
|
31
|
+
$ref: string;
|
|
32
|
+
};
|
|
33
|
+
export interface StateSpec {
|
|
34
|
+
schema: Record<string, StateFieldSchema>;
|
|
35
|
+
store?: string;
|
|
36
|
+
}
|
|
37
|
+
export interface PhaseSpec {
|
|
38
|
+
id: string;
|
|
39
|
+
title?: string;
|
|
40
|
+
}
|
|
41
|
+
export interface ToolNodeSpec {
|
|
42
|
+
id: string;
|
|
43
|
+
kind: 'tool';
|
|
44
|
+
phase?: string;
|
|
45
|
+
impl: string;
|
|
46
|
+
args?: Record<string, unknown>;
|
|
47
|
+
reads?: string[];
|
|
48
|
+
writes?: string[];
|
|
49
|
+
on_error?: ErrorPolicy;
|
|
50
|
+
for_each?: ForEachClause;
|
|
51
|
+
}
|
|
52
|
+
export interface AgentNodeSpec {
|
|
53
|
+
id: string;
|
|
54
|
+
kind: 'agent';
|
|
55
|
+
phase?: string;
|
|
56
|
+
prompt: string;
|
|
57
|
+
model?: string;
|
|
58
|
+
schema?: string | Record<string, unknown>;
|
|
59
|
+
reads?: string[];
|
|
60
|
+
writes?: string[];
|
|
61
|
+
args?: Record<string, unknown>;
|
|
62
|
+
on_error?: ErrorPolicy;
|
|
63
|
+
for_each?: ForEachClause;
|
|
64
|
+
}
|
|
65
|
+
export interface SkillNodeSpec {
|
|
66
|
+
id: string;
|
|
67
|
+
kind: 'skill';
|
|
68
|
+
phase?: string;
|
|
69
|
+
impl: string;
|
|
70
|
+
inputs?: Record<string, unknown>;
|
|
71
|
+
model?: string;
|
|
72
|
+
schema?: string | Record<string, unknown>;
|
|
73
|
+
reads?: string[];
|
|
74
|
+
writes?: string[];
|
|
75
|
+
on_error?: ErrorPolicy;
|
|
76
|
+
for_each?: ForEachClause;
|
|
77
|
+
}
|
|
78
|
+
export interface DatasetNodeSpec {
|
|
79
|
+
id: string;
|
|
80
|
+
kind: 'dataset';
|
|
81
|
+
phase?: string;
|
|
82
|
+
source: DatasetSource;
|
|
83
|
+
reads?: string[];
|
|
84
|
+
writes?: string[];
|
|
85
|
+
on_error?: ErrorPolicy;
|
|
86
|
+
for_each?: ForEachClause;
|
|
87
|
+
}
|
|
88
|
+
export interface ExperienceNodeSpec {
|
|
89
|
+
id: string;
|
|
90
|
+
kind: 'experience';
|
|
91
|
+
phase?: string;
|
|
92
|
+
impl: string;
|
|
93
|
+
args?: Record<string, unknown>;
|
|
94
|
+
state_scope?: 'shared' | 'isolated';
|
|
95
|
+
reads?: string[];
|
|
96
|
+
writes?: string[];
|
|
97
|
+
on_error?: ErrorPolicy;
|
|
98
|
+
for_each?: ForEachClause;
|
|
99
|
+
}
|
|
100
|
+
export interface CliAgentNodeSpec {
|
|
101
|
+
id: string;
|
|
102
|
+
kind: 'cli-agent';
|
|
103
|
+
phase?: string;
|
|
104
|
+
provider: 'claude-code' | 'codex' | 'gemini';
|
|
105
|
+
prompt: string;
|
|
106
|
+
model?: string;
|
|
107
|
+
workdir?: string;
|
|
108
|
+
output_format?: 'text' | 'json';
|
|
109
|
+
schema?: Record<string, unknown>;
|
|
110
|
+
timeout_ms?: number;
|
|
111
|
+
extra_args?: string[];
|
|
112
|
+
reads?: string[];
|
|
113
|
+
writes?: string[];
|
|
114
|
+
on_error?: ErrorPolicy;
|
|
115
|
+
for_each?: ForEachClause;
|
|
116
|
+
}
|
|
117
|
+
export type DatasetSource = {
|
|
118
|
+
type: 'file';
|
|
119
|
+
uri: string;
|
|
120
|
+
format?: 'json' | 'jsonl' | 'csv' | 'parquet';
|
|
121
|
+
transform?: string;
|
|
122
|
+
} | {
|
|
123
|
+
type: 'sqlite';
|
|
124
|
+
uri: string;
|
|
125
|
+
query: string;
|
|
126
|
+
} | {
|
|
127
|
+
type: 'http';
|
|
128
|
+
url: string;
|
|
129
|
+
method?: 'GET' | 'POST';
|
|
130
|
+
body?: unknown;
|
|
131
|
+
} | {
|
|
132
|
+
type: 'mcp-resource';
|
|
133
|
+
server: string;
|
|
134
|
+
uri: string;
|
|
135
|
+
};
|
|
136
|
+
export type NodeSpec = ToolNodeSpec | AgentNodeSpec | SkillNodeSpec | DatasetNodeSpec | ExperienceNodeSpec | CliAgentNodeSpec;
|
|
137
|
+
export type ErrorPolicy = {
|
|
138
|
+
policy: 'skip';
|
|
139
|
+
} | {
|
|
140
|
+
policy: 'fail_run';
|
|
141
|
+
} | {
|
|
142
|
+
policy: 'retry';
|
|
143
|
+
attempts: number;
|
|
144
|
+
backoff?: 'linear' | 'exponential';
|
|
145
|
+
base_ms?: number;
|
|
146
|
+
};
|
|
147
|
+
export interface EdgeSpec {
|
|
148
|
+
from: string;
|
|
149
|
+
to: string;
|
|
150
|
+
when?: string;
|
|
151
|
+
}
|
|
152
|
+
export interface GraphSpec {
|
|
153
|
+
nodes: NodeSpec[];
|
|
154
|
+
edges: EdgeSpec[];
|
|
155
|
+
pipelines?: PipelineGroupSpec[];
|
|
156
|
+
loops?: LoopSpec[];
|
|
157
|
+
}
|
|
158
|
+
export interface RuntimeSpec {
|
|
159
|
+
concurrency?: number;
|
|
160
|
+
}
|
|
161
|
+
export interface ExperienceSpec {
|
|
162
|
+
name: string;
|
|
163
|
+
description?: string;
|
|
164
|
+
version: string;
|
|
165
|
+
state: StateSpec;
|
|
166
|
+
phases?: PhaseSpec[];
|
|
167
|
+
graph: GraphSpec;
|
|
168
|
+
runtime?: RuntimeSpec;
|
|
169
|
+
}
|
|
170
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,0DAA0D;AAC1D,yEAAyE;AACzE,6EAA6E"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ExperienceSpec } from './types.js';
|
|
2
|
+
export declare class ValidationError extends Error {
|
|
3
|
+
readonly errors: string[];
|
|
4
|
+
constructor(message: string, errors?: string[]);
|
|
5
|
+
}
|
|
6
|
+
export declare function validateExperienceSpec(spec: unknown): asserts spec is ExperienceSpec;
|
|
7
|
+
//# sourceMappingURL=validator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../src/validator.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAUhD,qBAAa,eAAgB,SAAQ,KAAK;aAGtB,MAAM,EAAE,MAAM,EAAE;gBADhC,OAAO,EAAE,MAAM,EACC,MAAM,GAAE,MAAM,EAAO;CAKxC;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,IAAI,cAAc,CAqDpF"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import Ajv from 'ajv';
|
|
2
|
+
import addFormats from 'ajv-formats';
|
|
3
|
+
import { readFileSync } from 'node:fs';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
import { dirname, resolve } from 'node:path';
|
|
6
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
7
|
+
const schemaPath = resolve(__dirname, 'schemas/experience.schema.json');
|
|
8
|
+
const schema = JSON.parse(readFileSync(schemaPath, 'utf8'));
|
|
9
|
+
const ajv = new Ajv({ allErrors: true, strict: false });
|
|
10
|
+
addFormats(ajv);
|
|
11
|
+
const validateJsonSchema = ajv.compile(schema);
|
|
12
|
+
export class ValidationError extends Error {
|
|
13
|
+
errors;
|
|
14
|
+
constructor(message, errors = []) {
|
|
15
|
+
super(message);
|
|
16
|
+
this.errors = errors;
|
|
17
|
+
this.name = 'ValidationError';
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export function validateExperienceSpec(spec) {
|
|
21
|
+
if (!validateJsonSchema(spec)) {
|
|
22
|
+
const messages = (validateJsonSchema.errors ?? []).map((e) => `${e.instancePath || '(root)'}: ${e.message ?? 'invalid'}`);
|
|
23
|
+
throw new ValidationError(`Schema validation failed:\n${messages.join('\n')}`, messages);
|
|
24
|
+
}
|
|
25
|
+
// Beyond JSON Schema: referential integrity checks
|
|
26
|
+
const s = spec;
|
|
27
|
+
const nodeIds = new Set(s.graph.nodes.map((n) => n.id));
|
|
28
|
+
// Duplicate node ids first — every subsequent check assumes a structurally
|
|
29
|
+
// valid graph where the Set didn't silently dedupe collisions.
|
|
30
|
+
if (nodeIds.size !== s.graph.nodes.length) {
|
|
31
|
+
throw new ValidationError('Duplicate node ids in graph.nodes');
|
|
32
|
+
}
|
|
33
|
+
const definedNodeList = [...nodeIds].join(', ');
|
|
34
|
+
for (const edge of s.graph.edges) {
|
|
35
|
+
if (!nodeIds.has(edge.from)) {
|
|
36
|
+
throw new ValidationError(`Edge \`${edge.from} → ${edge.to}\` references node \`${edge.from}\` which doesn't exist. ` +
|
|
37
|
+
`Add it to \`graph.nodes:\` or fix the typo. ` +
|
|
38
|
+
`Defined nodes: ${definedNodeList || '(none)'}`);
|
|
39
|
+
}
|
|
40
|
+
if (!nodeIds.has(edge.to)) {
|
|
41
|
+
throw new ValidationError(`Edge \`${edge.from} → ${edge.to}\` references node \`${edge.to}\` which doesn't exist. ` +
|
|
42
|
+
`Add it to \`graph.nodes:\` or fix the typo. ` +
|
|
43
|
+
`Defined nodes: ${definedNodeList || '(none)'}`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
const declaredFields = new Set(Object.keys(s.state.schema));
|
|
47
|
+
for (const node of s.graph.nodes) {
|
|
48
|
+
for (const field of node.writes ?? []) {
|
|
49
|
+
if (!declaredFields.has(field)) {
|
|
50
|
+
throw new ValidationError(`Node "${node.id}" writes undeclared state field "${field}". Declare it in state.schema.`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
for (const field of node.reads ?? []) {
|
|
54
|
+
if (!declaredFields.has(field)) {
|
|
55
|
+
throw new ValidationError(`Node "${node.id}" reads undeclared state field "${field}". Declare it in state.schema.`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validator.js","sourceRoot":"","sources":["../src/validator.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,KAAK,CAAA;AACrB,OAAO,UAAU,MAAM,aAAa,CAAA;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AACxC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAG5C,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;AACzD,MAAM,UAAU,GAAG,OAAO,CAAC,SAAS,EAAE,gCAAgC,CAAC,CAAA;AACvE,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAA;AAE3D,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAA;AACvD,UAAU,CAAC,GAAG,CAAC,CAAA;AACf,MAAM,kBAAkB,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;AAE9C,MAAM,OAAO,eAAgB,SAAQ,KAAK;IAGtB;IAFlB,YACE,OAAe,EACC,SAAmB,EAAE;QAErC,KAAK,CAAC,OAAO,CAAC,CAAA;QAFE,WAAM,GAAN,MAAM,CAAe;QAGrC,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAA;IAC/B,CAAC;CACF;AAED,MAAM,UAAU,sBAAsB,CAAC,IAAa;IAClD,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC;QAC9B,MAAM,QAAQ,GAAG,CAAC,kBAAkB,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,GAAG,CACpD,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,YAAY,IAAI,QAAQ,KAAK,CAAC,CAAC,OAAO,IAAI,SAAS,EAAE,CAClE,CAAA;QACD,MAAM,IAAI,eAAe,CAAC,8BAA8B,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAA;IAC1F,CAAC;IAED,mDAAmD;IACnD,MAAM,CAAC,GAAG,IAAsB,CAAA;IAChC,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IAEvD,2EAA2E;IAC3E,+DAA+D;IAC/D,IAAI,OAAO,CAAC,IAAI,KAAK,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;QAC1C,MAAM,IAAI,eAAe,CAAC,mCAAmC,CAAC,CAAA;IAChE,CAAC;IAED,MAAM,eAAe,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAC/C,KAAK,MAAM,IAAI,IAAI,CAAC,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACjC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC5B,MAAM,IAAI,eAAe,CACvB,UAAU,IAAI,CAAC,IAAI,MAAM,IAAI,CAAC,EAAE,wBAAwB,IAAI,CAAC,IAAI,0BAA0B;gBACzF,8CAA8C;gBAC9C,kBAAkB,eAAe,IAAI,QAAQ,EAAE,CAClD,CAAA;QACH,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,eAAe,CACvB,UAAU,IAAI,CAAC,IAAI,MAAM,IAAI,CAAC,EAAE,wBAAwB,IAAI,CAAC,EAAE,0BAA0B;gBACvF,8CAA8C;gBAC9C,kBAAkB,eAAe,IAAI,QAAQ,EAAE,CAClD,CAAA;QACH,CAAC;IACH,CAAC;IAED,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAA;IAC3D,KAAK,MAAM,IAAI,IAAI,CAAC,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACjC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;YACtC,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC/B,MAAM,IAAI,eAAe,CACvB,SAAS,IAAI,CAAC,EAAE,oCAAoC,KAAK,gCAAgC,CAC1F,CAAA;YACH,CAAC;QACH,CAAC;QACD,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,KAAK,IAAI,EAAE,EAAE,CAAC;YACrC,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC/B,MAAM,IAAI,eAAe,CACvB,SAAS,IAAI,CAAC,EAAE,mCAAmC,KAAK,gCAAgC,CACzF,CAAA;YACH,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@openexpertise/schema",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "TypeScript types + JSON Schema + parser/validator for the OpenExpertise experience.yaml format.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"openexpertise",
|
|
7
|
+
"workflow",
|
|
8
|
+
"dag",
|
|
9
|
+
"llm",
|
|
10
|
+
"yaml",
|
|
11
|
+
"schema",
|
|
12
|
+
"json-schema",
|
|
13
|
+
"validation"
|
|
14
|
+
],
|
|
15
|
+
"author": "OpenExpertise contributors",
|
|
16
|
+
"license": "MIT",
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git+https://github.com/xingchengxu/OpenExpertise.git",
|
|
20
|
+
"directory": "packages/schema"
|
|
21
|
+
},
|
|
22
|
+
"bugs": {
|
|
23
|
+
"url": "https://github.com/xingchengxu/OpenExpertise/issues"
|
|
24
|
+
},
|
|
25
|
+
"homepage": "https://github.com/xingchengxu/OpenExpertise#readme",
|
|
26
|
+
"type": "module",
|
|
27
|
+
"main": "./dist/index.js",
|
|
28
|
+
"types": "./dist/index.d.ts",
|
|
29
|
+
"exports": {
|
|
30
|
+
".": {
|
|
31
|
+
"import": "./dist/index.js",
|
|
32
|
+
"types": "./dist/index.d.ts"
|
|
33
|
+
},
|
|
34
|
+
"./schema": "./src/schemas/experience.schema.json"
|
|
35
|
+
},
|
|
36
|
+
"files": [
|
|
37
|
+
"dist",
|
|
38
|
+
"src/schemas",
|
|
39
|
+
"README.md"
|
|
40
|
+
],
|
|
41
|
+
"publishConfig": {
|
|
42
|
+
"access": "public"
|
|
43
|
+
},
|
|
44
|
+
"dependencies": {
|
|
45
|
+
"ajv": "^8.17.0",
|
|
46
|
+
"ajv-formats": "^3.0.0",
|
|
47
|
+
"yaml": "^2.5.0"
|
|
48
|
+
},
|
|
49
|
+
"scripts": {
|
|
50
|
+
"build": "tsc -b && node -e \"require('node:fs').cpSync('src/schemas','dist/schemas',{recursive:true})\"",
|
|
51
|
+
"typecheck": "tsc --noEmit"
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://openexpertise.dev/schemas/experience-v0.1.0.json",
|
|
4
|
+
"title": "ExperienceSpec",
|
|
5
|
+
"_comment": "TODO Plan 2: tighten node oneOf variants with additionalProperties: false so typos like 'impl_path' don't pass validation and fail later at runtime.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["name", "version", "state", "graph"],
|
|
8
|
+
"additionalProperties": false,
|
|
9
|
+
"properties": {
|
|
10
|
+
"name": { "type": "string", "minLength": 1 },
|
|
11
|
+
"description": { "type": "string" },
|
|
12
|
+
"version": { "type": "string", "pattern": "^\\d+\\.\\d+\\.\\d+$" },
|
|
13
|
+
"state": {
|
|
14
|
+
"type": "object",
|
|
15
|
+
"required": ["schema"],
|
|
16
|
+
"additionalProperties": false,
|
|
17
|
+
"properties": {
|
|
18
|
+
"schema": {
|
|
19
|
+
"type": "object",
|
|
20
|
+
"additionalProperties": { "$ref": "#/$defs/stateField" }
|
|
21
|
+
},
|
|
22
|
+
"store": { "type": "string" }
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"phases": {
|
|
26
|
+
"type": "array",
|
|
27
|
+
"items": {
|
|
28
|
+
"type": "object",
|
|
29
|
+
"required": ["id"],
|
|
30
|
+
"additionalProperties": false,
|
|
31
|
+
"properties": {
|
|
32
|
+
"id": { "type": "string" },
|
|
33
|
+
"title": { "type": "string" }
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"graph": {
|
|
38
|
+
"type": "object",
|
|
39
|
+
"required": ["nodes", "edges"],
|
|
40
|
+
"additionalProperties": false,
|
|
41
|
+
"properties": {
|
|
42
|
+
"nodes": {
|
|
43
|
+
"type": "array",
|
|
44
|
+
"minItems": 1,
|
|
45
|
+
"items": { "$ref": "#/$defs/node" }
|
|
46
|
+
},
|
|
47
|
+
"edges": {
|
|
48
|
+
"type": "array",
|
|
49
|
+
"items": { "$ref": "#/$defs/edge" }
|
|
50
|
+
},
|
|
51
|
+
"pipelines": {
|
|
52
|
+
"type": "array",
|
|
53
|
+
"items": {
|
|
54
|
+
"type": "object",
|
|
55
|
+
"required": ["id", "items", "stages"],
|
|
56
|
+
"additionalProperties": false,
|
|
57
|
+
"properties": {
|
|
58
|
+
"id": { "type": "string" },
|
|
59
|
+
"items": { "type": "string" },
|
|
60
|
+
"stages": { "type": "array", "items": { "type": "string" }, "minItems": 1 },
|
|
61
|
+
"phase": { "type": "string" }
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
"loops": {
|
|
66
|
+
"type": "array",
|
|
67
|
+
"items": {
|
|
68
|
+
"type": "object",
|
|
69
|
+
"required": ["id", "body"],
|
|
70
|
+
"additionalProperties": false,
|
|
71
|
+
"properties": {
|
|
72
|
+
"id": { "type": "string" },
|
|
73
|
+
"body": { "type": "string" },
|
|
74
|
+
"until": { "type": "string" },
|
|
75
|
+
"max_iters": { "type": "integer", "minimum": 1 },
|
|
76
|
+
"budget": { "type": "integer", "minimum": 0 },
|
|
77
|
+
"phase": { "type": "string" }
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
"runtime": {
|
|
84
|
+
"type": "object",
|
|
85
|
+
"additionalProperties": false,
|
|
86
|
+
"properties": {
|
|
87
|
+
"concurrency": { "type": "integer", "minimum": 1 }
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
"$defs": {
|
|
92
|
+
"stateField": {
|
|
93
|
+
"type": "object",
|
|
94
|
+
"additionalProperties": true,
|
|
95
|
+
"properties": {
|
|
96
|
+
"type": {
|
|
97
|
+
"type": "string",
|
|
98
|
+
"enum": ["string", "number", "boolean", "object", "array", "null"]
|
|
99
|
+
},
|
|
100
|
+
"description": { "type": "string" },
|
|
101
|
+
"merge": { "enum": ["array_append", "set_once", "last_wins"] }
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
"edge": {
|
|
105
|
+
"type": "object",
|
|
106
|
+
"required": ["from", "to"],
|
|
107
|
+
"additionalProperties": false,
|
|
108
|
+
"properties": {
|
|
109
|
+
"from": { "type": "string" },
|
|
110
|
+
"to": { "type": "string" },
|
|
111
|
+
"when": { "type": "string" }
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
"errorPolicy": {
|
|
115
|
+
"oneOf": [
|
|
116
|
+
{
|
|
117
|
+
"type": "object",
|
|
118
|
+
"required": ["policy"],
|
|
119
|
+
"properties": { "policy": { "const": "skip" } },
|
|
120
|
+
"additionalProperties": false
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
"type": "object",
|
|
124
|
+
"required": ["policy"],
|
|
125
|
+
"properties": { "policy": { "const": "fail_run" } },
|
|
126
|
+
"additionalProperties": false
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
"type": "object",
|
|
130
|
+
"required": ["policy", "attempts"],
|
|
131
|
+
"properties": {
|
|
132
|
+
"policy": { "const": "retry" },
|
|
133
|
+
"attempts": { "type": "integer", "minimum": 1, "maximum": 20 },
|
|
134
|
+
"backoff": { "enum": ["linear", "exponential"] },
|
|
135
|
+
"base_ms": { "type": "integer", "minimum": 0 }
|
|
136
|
+
},
|
|
137
|
+
"additionalProperties": false
|
|
138
|
+
}
|
|
139
|
+
]
|
|
140
|
+
},
|
|
141
|
+
"nodeBase": {
|
|
142
|
+
"type": "object",
|
|
143
|
+
"required": ["id", "kind"],
|
|
144
|
+
"properties": {
|
|
145
|
+
"id": { "type": "string", "minLength": 1, "pattern": "^[a-zA-Z_][a-zA-Z0-9_]*$" },
|
|
146
|
+
"phase": { "type": "string" },
|
|
147
|
+
"reads": { "type": "array", "items": { "type": "string" } },
|
|
148
|
+
"writes": { "type": "array", "items": { "type": "string" } },
|
|
149
|
+
"on_error": { "$ref": "#/$defs/errorPolicy" },
|
|
150
|
+
"for_each": {
|
|
151
|
+
"type": "object",
|
|
152
|
+
"required": ["source"],
|
|
153
|
+
"properties": {
|
|
154
|
+
"source": { "type": "string" },
|
|
155
|
+
"concurrency": { "type": "integer", "minimum": 1 }
|
|
156
|
+
},
|
|
157
|
+
"additionalProperties": false
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
},
|
|
161
|
+
"node": {
|
|
162
|
+
"oneOf": [
|
|
163
|
+
{
|
|
164
|
+
"allOf": [
|
|
165
|
+
{ "$ref": "#/$defs/nodeBase" },
|
|
166
|
+
{
|
|
167
|
+
"type": "object",
|
|
168
|
+
"required": ["impl"],
|
|
169
|
+
"properties": {
|
|
170
|
+
"kind": { "const": "tool" },
|
|
171
|
+
"impl": { "type": "string" },
|
|
172
|
+
"args": { "type": "object" }
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
]
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
"allOf": [
|
|
179
|
+
{ "$ref": "#/$defs/nodeBase" },
|
|
180
|
+
{
|
|
181
|
+
"type": "object",
|
|
182
|
+
"required": ["prompt"],
|
|
183
|
+
"properties": {
|
|
184
|
+
"kind": { "const": "agent" },
|
|
185
|
+
"prompt": { "type": "string" },
|
|
186
|
+
"model": { "type": "string" },
|
|
187
|
+
"schema": {},
|
|
188
|
+
"args": { "type": "object" }
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
]
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
"allOf": [
|
|
195
|
+
{ "$ref": "#/$defs/nodeBase" },
|
|
196
|
+
{
|
|
197
|
+
"type": "object",
|
|
198
|
+
"required": ["impl"],
|
|
199
|
+
"properties": {
|
|
200
|
+
"kind": { "const": "skill" },
|
|
201
|
+
"impl": { "type": "string" },
|
|
202
|
+
"inputs": { "type": "object" },
|
|
203
|
+
"model": { "type": "string" },
|
|
204
|
+
"schema": {}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
]
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
"allOf": [
|
|
211
|
+
{ "$ref": "#/$defs/nodeBase" },
|
|
212
|
+
{
|
|
213
|
+
"type": "object",
|
|
214
|
+
"required": ["source"],
|
|
215
|
+
"properties": {
|
|
216
|
+
"kind": { "const": "dataset" },
|
|
217
|
+
"source": { "type": "object" }
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
]
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
"allOf": [
|
|
224
|
+
{ "$ref": "#/$defs/nodeBase" },
|
|
225
|
+
{
|
|
226
|
+
"type": "object",
|
|
227
|
+
"required": ["impl"],
|
|
228
|
+
"properties": {
|
|
229
|
+
"kind": { "const": "experience" },
|
|
230
|
+
"impl": { "type": "string" },
|
|
231
|
+
"args": { "type": "object" },
|
|
232
|
+
"state_scope": { "enum": ["shared", "isolated"] }
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
]
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
"allOf": [
|
|
239
|
+
{ "$ref": "#/$defs/nodeBase" },
|
|
240
|
+
{
|
|
241
|
+
"type": "object",
|
|
242
|
+
"required": ["provider", "prompt"],
|
|
243
|
+
"properties": {
|
|
244
|
+
"kind": { "const": "cli-agent" },
|
|
245
|
+
"provider": { "enum": ["claude-code", "codex", "gemini"] },
|
|
246
|
+
"prompt": { "type": "string", "minLength": 1 },
|
|
247
|
+
"model": { "type": "string" },
|
|
248
|
+
"workdir": { "type": "string" },
|
|
249
|
+
"output_format": { "enum": ["text", "json"] },
|
|
250
|
+
"schema": {},
|
|
251
|
+
"timeout_ms": { "type": "integer", "minimum": 1000 },
|
|
252
|
+
"extra_args": { "type": "array", "items": { "type": "string" } }
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
]
|
|
256
|
+
}
|
|
257
|
+
]
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|