openagentflow 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/README.md +262 -0
- package/adapters/langgraph/demo_template.js +104 -0
- package/adapters/langgraph/index.js +363 -0
- package/adapters/langgraph/templates.js +502 -0
- package/cli/env.js +193 -0
- package/cli/index.js +580 -0
- package/compiler/compiler.js +134 -0
- package/compiler/index.js +7 -0
- package/compiler/ir-generator.js +142 -0
- package/compiler/validator.js +594 -0
- package/examples/hello.oaf +14 -0
- package/examples/software-dev.oaf +60 -0
- package/examples/summarize-input.json +3 -0
- package/examples/summarize.oaf +28 -0
- package/examples/support-triage-input.json +3 -0
- package/examples/support-triage.oaf +49 -0
- package/package.json +44 -0
- package/parser/ast.js +240 -0
- package/parser/index.js +9 -0
- package/parser/lexer.js +376 -0
- package/parser/parser.js +505 -0
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
{
|
|
2
|
+
"customer_email": "Subject: URGENT: Extremely disappointed with Order #48291 - Damaged Items and Poor Service\n\nTo Whom It May Concern,\n\nI am writing to express my immense frustration regarding my recent order (#48291), placed on July 5th. \n\nNot only did the package arrive a full week past your guaranteed delivery date, but when I finally opened it today, two of the three items I ordered were completely shattered. The box had barely any bubble wrap or protective packaging, which is frankly unacceptable for fragile goods. \n\nI ordered these specifically for an important event happening tomorrow, and now I am left scrambling for a last-minute replacement because of your shipping department's negligence. Furthermore, I tried calling your customer support line three times today, only to be left on hold for over 30 minutes each time before being disconnected.\n\nI expect a full refund for this order immediately. I have attached photos of the damaged items and the inadequate packaging to this email. \n\nI look forward to your prompt response. If I do not hear back within 24 hours to resolve this issue, I will be forced to dispute the charge with my credit card company.\n\nRegretfully,\n\nAlex Mercer\nalex.mercer@email.com\n(555) 123-4567"
|
|
3
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// A linear workflow that triages inbound messages and drafts replies.
|
|
2
|
+
workflow "SupportTriage" {
|
|
3
|
+
|
|
4
|
+
state {
|
|
5
|
+
customer_email: string @required
|
|
6
|
+
categories: list[string]
|
|
7
|
+
urgency: int
|
|
8
|
+
draft_response: string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
flow {
|
|
12
|
+
start -> Classifier
|
|
13
|
+
Classifier -> Drafter
|
|
14
|
+
Drafter -> end
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
config {
|
|
18
|
+
version: "1.0"
|
|
19
|
+
runtime: "langgraph"
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
agent Classifier {
|
|
23
|
+
model: "gemini-3.1-flash-lite"
|
|
24
|
+
temperature: 0.1
|
|
25
|
+
instructions: """
|
|
26
|
+
Analyze the inbound customer_email.
|
|
27
|
+
Determine the issue category (e.g., Billing, TechSupport, FeatureRequest).
|
|
28
|
+
Assign an urgency score from 1 (routine) to 5 (critical escalation).
|
|
29
|
+
"""
|
|
30
|
+
inputs: [customer_email]
|
|
31
|
+
outputs: [categories, urgency]
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
agent Drafter {
|
|
35
|
+
model: "gemma-4-26b-a4b-it"
|
|
36
|
+
temperature: 0.7
|
|
37
|
+
instructions: """
|
|
38
|
+
Write a polite, empathetic response addressing the customer's issue.
|
|
39
|
+
Tailor the tone based on the categories and urgency.
|
|
40
|
+
If urgency is 4 or 5, assure them a senior human agent is being alerted.
|
|
41
|
+
Leave placeholders like [Your Name] for account details.
|
|
42
|
+
"""
|
|
43
|
+
inputs: [customer_email, categories, urgency]
|
|
44
|
+
outputs: [draft_response]
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "openagentflow",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "An open, portable specification for describing AI agent workflows using a human-readable text language.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "compiler/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"oaf": "cli/index.js"
|
|
9
|
+
},
|
|
10
|
+
"exports": {
|
|
11
|
+
".": "./compiler/index.js",
|
|
12
|
+
"./parser": "./parser/index.js",
|
|
13
|
+
"./adapters/langgraph": "./adapters/langgraph/index.js",
|
|
14
|
+
"./cli": "./cli/index.js",
|
|
15
|
+
"./package.json": "./package.json"
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"cli",
|
|
19
|
+
"compiler",
|
|
20
|
+
"parser",
|
|
21
|
+
"adapters",
|
|
22
|
+
"examples",
|
|
23
|
+
"README.md",
|
|
24
|
+
"LICENSE"
|
|
25
|
+
],
|
|
26
|
+
"scripts": {
|
|
27
|
+
"test": "node --test tests/**/*.test.js",
|
|
28
|
+
"oaf": "node cli/index.js"
|
|
29
|
+
},
|
|
30
|
+
"keywords": [
|
|
31
|
+
"ai",
|
|
32
|
+
"agents",
|
|
33
|
+
"workflow",
|
|
34
|
+
"dsl",
|
|
35
|
+
"langgraph",
|
|
36
|
+
"autogen",
|
|
37
|
+
"crewai",
|
|
38
|
+
"openagentflow"
|
|
39
|
+
],
|
|
40
|
+
"license": "MIT",
|
|
41
|
+
"engines": {
|
|
42
|
+
"node": ">=18.0.0"
|
|
43
|
+
}
|
|
44
|
+
}
|
package/parser/ast.js
ADDED
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAgentFlow AST Node Definitions
|
|
3
|
+
*
|
|
4
|
+
* Defines all node types produced by the parser.
|
|
5
|
+
* Each node captures its source location for diagnostic reporting.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// ─── Base Node ─────────────────────────────────────────────────────────────────
|
|
9
|
+
|
|
10
|
+
export class ASTNode {
|
|
11
|
+
/**
|
|
12
|
+
* @param {string} type - Node type identifier
|
|
13
|
+
* @param {number} line - Source line
|
|
14
|
+
* @param {number} column - Source column
|
|
15
|
+
*/
|
|
16
|
+
constructor(type, line, column) {
|
|
17
|
+
this.type = type;
|
|
18
|
+
this.line = line;
|
|
19
|
+
this.column = column;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// ─── Program ───────────────────────────────────────────────────────────────────
|
|
24
|
+
|
|
25
|
+
export class Program extends ASTNode {
|
|
26
|
+
/**
|
|
27
|
+
* @param {WorkflowDecl} workflow
|
|
28
|
+
*/
|
|
29
|
+
constructor(workflow) {
|
|
30
|
+
super('Program', workflow.line, workflow.column);
|
|
31
|
+
this.workflow = workflow;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// ─── Workflow Declaration ──────────────────────────────────────────────────────
|
|
36
|
+
|
|
37
|
+
export class WorkflowDecl extends ASTNode {
|
|
38
|
+
/**
|
|
39
|
+
* @param {string} name - Workflow name
|
|
40
|
+
* @param {StateBlock|null} state
|
|
41
|
+
* @param {AgentBlock[]} agents
|
|
42
|
+
* @param {FlowBlock} flow
|
|
43
|
+
* @param {ConfigBlock|null} config
|
|
44
|
+
* @param {number} line
|
|
45
|
+
* @param {number} column
|
|
46
|
+
*/
|
|
47
|
+
constructor(name, state, agents, flow, config, line, column) {
|
|
48
|
+
super('WorkflowDecl', line, column);
|
|
49
|
+
this.name = name;
|
|
50
|
+
this.state = state;
|
|
51
|
+
this.agents = agents;
|
|
52
|
+
this.flow = flow;
|
|
53
|
+
this.config = config;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// ─── State Block ───────────────────────────────────────────────────────────────
|
|
58
|
+
|
|
59
|
+
export class StateBlock extends ASTNode {
|
|
60
|
+
/**
|
|
61
|
+
* @param {StateField[]} fields
|
|
62
|
+
* @param {number} line
|
|
63
|
+
* @param {number} column
|
|
64
|
+
*/
|
|
65
|
+
constructor(fields, line, column) {
|
|
66
|
+
super('StateBlock', line, column);
|
|
67
|
+
this.fields = fields;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export class StateField extends ASTNode {
|
|
72
|
+
/**
|
|
73
|
+
* @param {string} name - Variable name
|
|
74
|
+
* @param {TypeExpr} typeExpr - Type expression
|
|
75
|
+
* @param {StateOption[]} options - State field options
|
|
76
|
+
* @param {number} line
|
|
77
|
+
* @param {number} column
|
|
78
|
+
*/
|
|
79
|
+
constructor(name, typeExpr, options = [], line, column) {
|
|
80
|
+
if (typeof options === 'number') {
|
|
81
|
+
column = line;
|
|
82
|
+
line = options;
|
|
83
|
+
options = [];
|
|
84
|
+
}
|
|
85
|
+
super('StateField', line, column);
|
|
86
|
+
this.name = name;
|
|
87
|
+
this.typeExpr = typeExpr;
|
|
88
|
+
this.options = options;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export class StateOption extends ASTNode {
|
|
93
|
+
/**
|
|
94
|
+
* @param {string} name - Option name (without @)
|
|
95
|
+
* @param {Array<*>} args - Option arguments
|
|
96
|
+
* @param {number} line
|
|
97
|
+
* @param {number} column
|
|
98
|
+
*/
|
|
99
|
+
constructor(name, args = [], line, column) {
|
|
100
|
+
super('StateOption', line, column);
|
|
101
|
+
this.name = name;
|
|
102
|
+
this.args = args;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// ─── Type Expressions ──────────────────────────────────────────────────────────
|
|
107
|
+
|
|
108
|
+
export class TypeExpr extends ASTNode {
|
|
109
|
+
/**
|
|
110
|
+
* @param {string} kind - 'primitive' | 'list' | 'map'
|
|
111
|
+
* @param {number} line
|
|
112
|
+
* @param {number} column
|
|
113
|
+
*/
|
|
114
|
+
constructor(kind, line, column) {
|
|
115
|
+
super('TypeExpr', line, column);
|
|
116
|
+
this.kind = kind;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export class PrimitiveType extends TypeExpr {
|
|
121
|
+
/**
|
|
122
|
+
* @param {string} name - 'string' | 'int' | 'float' | 'bool'
|
|
123
|
+
* @param {number} line
|
|
124
|
+
* @param {number} column
|
|
125
|
+
*/
|
|
126
|
+
constructor(name, line, column) {
|
|
127
|
+
super('primitive', line, column);
|
|
128
|
+
this.name = name;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export class ListType extends TypeExpr {
|
|
133
|
+
/**
|
|
134
|
+
* @param {TypeExpr} elementType
|
|
135
|
+
* @param {number} line
|
|
136
|
+
* @param {number} column
|
|
137
|
+
*/
|
|
138
|
+
constructor(elementType, line, column) {
|
|
139
|
+
super('list', line, column);
|
|
140
|
+
this.elementType = elementType;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export class MapType extends TypeExpr {
|
|
145
|
+
/**
|
|
146
|
+
* @param {TypeExpr} keyType
|
|
147
|
+
* @param {TypeExpr} valueType
|
|
148
|
+
* @param {number} line
|
|
149
|
+
* @param {number} column
|
|
150
|
+
*/
|
|
151
|
+
constructor(keyType, valueType, line, column) {
|
|
152
|
+
super('map', line, column);
|
|
153
|
+
this.keyType = keyType;
|
|
154
|
+
this.valueType = valueType;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// ─── Agent Block ───────────────────────────────────────────────────────────────
|
|
159
|
+
|
|
160
|
+
export class AgentBlock extends ASTNode {
|
|
161
|
+
/**
|
|
162
|
+
* @param {string} id - Agent identifier
|
|
163
|
+
* @param {Object} properties - Parsed properties
|
|
164
|
+
* @param {string} properties.instructions - Required instructions
|
|
165
|
+
* @param {string|null} properties.model
|
|
166
|
+
* @param {number|null} properties.temperature
|
|
167
|
+
* @param {string[]} properties.tools
|
|
168
|
+
* @param {string[]} properties.inputs
|
|
169
|
+
* @param {string[]} properties.outputs
|
|
170
|
+
* @param {number} line
|
|
171
|
+
* @param {number} column
|
|
172
|
+
*/
|
|
173
|
+
constructor(id, properties, line, column) {
|
|
174
|
+
super('AgentBlock', line, column);
|
|
175
|
+
this.id = id;
|
|
176
|
+
this.instructions = properties.instructions;
|
|
177
|
+
this.model = properties.model ?? null;
|
|
178
|
+
this.provider = properties.provider ?? null;
|
|
179
|
+
this.temperature = properties.temperature ?? null;
|
|
180
|
+
this.tools = properties.tools ?? [];
|
|
181
|
+
this.inputs = properties.inputs ?? [];
|
|
182
|
+
this.outputs = properties.outputs ?? [];
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// ─── Flow Block ────────────────────────────────────────────────────────────────
|
|
187
|
+
|
|
188
|
+
export class FlowBlock extends ASTNode {
|
|
189
|
+
/**
|
|
190
|
+
* @param {Edge[]} edges
|
|
191
|
+
* @param {number} line
|
|
192
|
+
* @param {number} column
|
|
193
|
+
*/
|
|
194
|
+
constructor(edges, line, column) {
|
|
195
|
+
super('FlowBlock', line, column);
|
|
196
|
+
this.edges = edges;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
export class Edge extends ASTNode {
|
|
201
|
+
/**
|
|
202
|
+
* @param {string} source
|
|
203
|
+
* @param {string} target
|
|
204
|
+
* @param {number} line
|
|
205
|
+
* @param {number} column
|
|
206
|
+
*/
|
|
207
|
+
constructor(source, target, line, column) {
|
|
208
|
+
super('Edge', line, column);
|
|
209
|
+
this.source = source;
|
|
210
|
+
this.target = target;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// ─── Config Block ──────────────────────────────────────────────────────────────
|
|
215
|
+
|
|
216
|
+
export class ConfigBlock extends ASTNode {
|
|
217
|
+
/**
|
|
218
|
+
* @param {ConfigEntry[]} entries
|
|
219
|
+
* @param {number} line
|
|
220
|
+
* @param {number} column
|
|
221
|
+
*/
|
|
222
|
+
constructor(entries, line, column) {
|
|
223
|
+
super('ConfigBlock', line, column);
|
|
224
|
+
this.entries = entries;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
export class ConfigEntry extends ASTNode {
|
|
229
|
+
/**
|
|
230
|
+
* @param {string} key
|
|
231
|
+
* @param {*} value
|
|
232
|
+
* @param {number} line
|
|
233
|
+
* @param {number} column
|
|
234
|
+
*/
|
|
235
|
+
constructor(key, value, line, column) {
|
|
236
|
+
super('ConfigEntry', line, column);
|
|
237
|
+
this.key = key;
|
|
238
|
+
this.value = value;
|
|
239
|
+
}
|
|
240
|
+
}
|
package/parser/index.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAgentFlow Parser — Public API
|
|
3
|
+
*
|
|
4
|
+
* Re-exports the lexer, parser, and AST for external consumers.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export { Lexer, Token, TokenType, LexerError } from './lexer.js';
|
|
8
|
+
export { Parser, ParseError } from './parser.js';
|
|
9
|
+
export * from './ast.js';
|