@koi-language/koi 1.0.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/QUICKSTART.md +89 -0
- package/README.md +545 -0
- package/examples/actions-demo.koi +177 -0
- package/examples/cache-test.koi +29 -0
- package/examples/calculator.koi +61 -0
- package/examples/clear-registry.js +33 -0
- package/examples/clear-registry.koi +30 -0
- package/examples/code-introspection-test.koi +149 -0
- package/examples/counter.koi +132 -0
- package/examples/delegation-test.koi +52 -0
- package/examples/directory-import-test.koi +84 -0
- package/examples/hello-world-claude.koi +52 -0
- package/examples/hello-world.koi +52 -0
- package/examples/hello.koi +24 -0
- package/examples/mcp-example.koi +70 -0
- package/examples/multi-event-handler-test.koi +144 -0
- package/examples/new-import-test.koi +89 -0
- package/examples/pipeline.koi +162 -0
- package/examples/registry-demo.koi +184 -0
- package/examples/registry-playbook-demo.koi +162 -0
- package/examples/registry-playbook-email-compositor-2.koi +140 -0
- package/examples/registry-playbook-email-compositor.koi +140 -0
- package/examples/sentiment.koi +90 -0
- package/examples/simple.koi +48 -0
- package/examples/skill-import-test.koi +76 -0
- package/examples/skills/advanced/index.koi +95 -0
- package/examples/skills/math-operations.koi +69 -0
- package/examples/skills/string-operations.koi +56 -0
- package/examples/task-chaining-demo.koi +244 -0
- package/examples/test-await.koi +22 -0
- package/examples/test-crypto-sha256.koi +196 -0
- package/examples/test-delegation.koi +41 -0
- package/examples/test-multi-team-routing.koi +258 -0
- package/examples/test-no-handler.koi +35 -0
- package/examples/test-npm-import.koi +67 -0
- package/examples/test-parse.koi +10 -0
- package/examples/test-peers-with-team.koi +59 -0
- package/examples/test-permissions-fail.koi +20 -0
- package/examples/test-permissions.koi +36 -0
- package/examples/test-simple-registry.koi +31 -0
- package/examples/test-typescript-import.koi +64 -0
- package/examples/test-uses-team-syntax.koi +25 -0
- package/examples/test-uses-team.koi +31 -0
- package/examples/utils/calculator.test.ts +144 -0
- package/examples/utils/calculator.ts +56 -0
- package/examples/utils/math-helpers.js +50 -0
- package/examples/utils/math-helpers.ts +55 -0
- package/examples/web-delegation-demo.koi +165 -0
- package/package.json +78 -0
- package/src/cli/koi.js +793 -0
- package/src/compiler/build-optimizer.js +447 -0
- package/src/compiler/cache-manager.js +274 -0
- package/src/compiler/import-resolver.js +369 -0
- package/src/compiler/parser.js +7542 -0
- package/src/compiler/transpiler.js +1105 -0
- package/src/compiler/typescript-transpiler.js +148 -0
- package/src/grammar/koi.pegjs +767 -0
- package/src/runtime/action-registry.js +172 -0
- package/src/runtime/actions/call-skill.js +45 -0
- package/src/runtime/actions/format.js +115 -0
- package/src/runtime/actions/print.js +42 -0
- package/src/runtime/actions/registry-delete.js +37 -0
- package/src/runtime/actions/registry-get.js +37 -0
- package/src/runtime/actions/registry-keys.js +33 -0
- package/src/runtime/actions/registry-search.js +34 -0
- package/src/runtime/actions/registry-set.js +50 -0
- package/src/runtime/actions/return.js +31 -0
- package/src/runtime/actions/send-message.js +58 -0
- package/src/runtime/actions/update-state.js +36 -0
- package/src/runtime/agent.js +1368 -0
- package/src/runtime/cli-logger.js +205 -0
- package/src/runtime/incremental-json-parser.js +201 -0
- package/src/runtime/index.js +33 -0
- package/src/runtime/llm-provider.js +1372 -0
- package/src/runtime/mcp-client.js +1171 -0
- package/src/runtime/planner.js +273 -0
- package/src/runtime/registry-backends/keyv-sqlite.js +215 -0
- package/src/runtime/registry-backends/local.js +260 -0
- package/src/runtime/registry.js +162 -0
- package/src/runtime/role.js +14 -0
- package/src/runtime/router.js +395 -0
- package/src/runtime/runtime.js +113 -0
- package/src/runtime/skill-selector.js +173 -0
- package/src/runtime/skill.js +25 -0
- package/src/runtime/team.js +162 -0
|
@@ -0,0 +1,767 @@
|
|
|
1
|
+
// ============================================================
|
|
2
|
+
// ZenScript Grammar - Peggy PEG
|
|
3
|
+
// ============================================================
|
|
4
|
+
|
|
5
|
+
{
|
|
6
|
+
function buildBinaryExpression(head, tail) {
|
|
7
|
+
return tail.reduce((acc, [_, op, __, expr]) => ({
|
|
8
|
+
type: 'BinaryExpression',
|
|
9
|
+
operator: op,
|
|
10
|
+
left: acc,
|
|
11
|
+
right: expr,
|
|
12
|
+
location: location()
|
|
13
|
+
}), head);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// ============================================================
|
|
18
|
+
// Top-level program
|
|
19
|
+
// ============================================================
|
|
20
|
+
|
|
21
|
+
Program
|
|
22
|
+
= _ decls:Declaration* _ {
|
|
23
|
+
return {
|
|
24
|
+
type: 'Program',
|
|
25
|
+
declarations: decls.filter(d => d !== null),
|
|
26
|
+
location: location()
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
Declaration
|
|
31
|
+
= PackageDecl
|
|
32
|
+
/ ImportDecl
|
|
33
|
+
/ RoleDecl
|
|
34
|
+
/ TeamDecl
|
|
35
|
+
/ AgentDecl
|
|
36
|
+
/ SkillDecl
|
|
37
|
+
/ RunStatement
|
|
38
|
+
|
|
39
|
+
// ============================================================
|
|
40
|
+
// Package
|
|
41
|
+
// ============================================================
|
|
42
|
+
|
|
43
|
+
PackageDecl
|
|
44
|
+
= "package"i _ name:StringLiteral _ {
|
|
45
|
+
return { type: 'PackageDecl', name, location: location() };
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// ============================================================
|
|
49
|
+
// Import (TypeScript/JavaScript style)
|
|
50
|
+
// ============================================================
|
|
51
|
+
|
|
52
|
+
ImportDecl
|
|
53
|
+
= "import"i _ name:StringLiteral _ {
|
|
54
|
+
return { type: 'ImportDecl', what: 'module', name, location: location() };
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// ============================================================
|
|
58
|
+
// Role
|
|
59
|
+
// ============================================================
|
|
60
|
+
|
|
61
|
+
RoleDecl
|
|
62
|
+
= "role"i _ name:Identifier _ "{" _ caps:RoleCapabilities _ "}" _ {
|
|
63
|
+
return { type: 'RoleDecl', name, capabilities: caps, location: location() };
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
RoleCapabilities
|
|
67
|
+
= head:RoleCapability tail:(_ "," _ RoleCapability)* _ ","? {
|
|
68
|
+
return [head, ...tail.map(t => t[3])];
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
RoleCapability
|
|
72
|
+
= "can"i _ name:Identifier {
|
|
73
|
+
return { type: 'Capability', name, location: location() };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// ============================================================
|
|
77
|
+
// Team
|
|
78
|
+
// ============================================================
|
|
79
|
+
|
|
80
|
+
TeamDecl
|
|
81
|
+
= "Team"i _ name:Identifier _ override:TeamOverride? _ "{" _ members:TeamMembers _ "}" _ {
|
|
82
|
+
return { type: 'TeamDecl', name, override, members, location: location() };
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
TeamOverride
|
|
86
|
+
= "override"i _ "{" _ overrides:TeamMembers _ "}" {
|
|
87
|
+
return overrides;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
TeamMembers
|
|
91
|
+
= head:TeamMember tail:(_ TeamMember)* {
|
|
92
|
+
return [head, ...tail.map(t => t[1])];
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
TeamMember
|
|
96
|
+
= name:Identifier _ "=" _ value:(MCPAddress / StringLiteral / Identifier) _ {
|
|
97
|
+
return { name, value, location: location() };
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// ============================================================
|
|
101
|
+
// Agent
|
|
102
|
+
// ============================================================
|
|
103
|
+
|
|
104
|
+
AgentDecl
|
|
105
|
+
= "Agent"i _ name:Identifier _ ":" _ role:Identifier _ "{" _ body:AgentBody _ "}" _ {
|
|
106
|
+
return { type: 'AgentDecl', name, role, body, location: location() };
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
AgentBody
|
|
110
|
+
= items:(AgentBodyItem)* {
|
|
111
|
+
// Flatten any arrays (for comma-separated uses statements)
|
|
112
|
+
return items.flat();
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
AgentBodyItem
|
|
116
|
+
= UsesSkill
|
|
117
|
+
/ UsesTeam
|
|
118
|
+
/ LLMConfig
|
|
119
|
+
/ EventHandler
|
|
120
|
+
/ StateDecl
|
|
121
|
+
/ PlaybookDecl
|
|
122
|
+
/ ResilienceDecl
|
|
123
|
+
/ ExportFunction
|
|
124
|
+
|
|
125
|
+
UsesSkill
|
|
126
|
+
= "uses"i _ "skill"i _ names:IdentifierList _ {
|
|
127
|
+
return names.map(name => ({ type: 'UsesSkill', skill: name, location: location() }));
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
UsesTeam
|
|
131
|
+
= "uses"i _ "team"i _ names:IdentifierList _ {
|
|
132
|
+
return names.map(name => ({ type: 'UsesTeam', team: name, location: location() }));
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Comma-separated list of identifiers
|
|
136
|
+
IdentifierList
|
|
137
|
+
= first:Identifier rest:(_ "," _ Identifier)* {
|
|
138
|
+
return [first, ...rest.map(r => r[3])];
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
LLMConfig
|
|
142
|
+
= "llm"i _ "default"i _ "=" _ config:ObjectLiteral _ {
|
|
143
|
+
return { type: 'LLMConfig', config, location: location() };
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
EventHandler
|
|
147
|
+
= "on"i _ event:HandlerName _ "(" _ params:Parameters? _ ")" _ "{" _ body:Statement* _ "}" _ {
|
|
148
|
+
return { type: 'EventHandler', event, params: params || [], body, location: location() };
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
HandlerName
|
|
152
|
+
= name:$([a-zA-Z_][a-zA-Z0-9_]*) &{
|
|
153
|
+
const reserved = ['run', 'package', 'import', 'skill', 'role', 'can', 'Team', 'Agent', 'Skill',
|
|
154
|
+
'uses', 'llm', 'default', 'on', 'state', 'playbook', 'resilience',
|
|
155
|
+
'export', 'async', 'function', 'var', 'const', 'let', 'if', 'else', 'for', 'of', 'in', 'while',
|
|
156
|
+
'return', 'await', 'send', 'timeout', 'use', 'override', 'affordance',
|
|
157
|
+
'true', 'false', 'null'];
|
|
158
|
+
if (reserved.includes(name.toLowerCase())) {
|
|
159
|
+
error(`'${name}' is a reserved keyword and cannot be used as a handler name.\n` +
|
|
160
|
+
`Use a different name like 'start', 'execute', 'process', or '${name}Handler'.`);
|
|
161
|
+
}
|
|
162
|
+
return true;
|
|
163
|
+
} {
|
|
164
|
+
return { type: 'Identifier', name, location: location() };
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
StateDecl
|
|
168
|
+
= "state"i _ "{" _ fields:StateFields _ "}" _ {
|
|
169
|
+
return { type: 'StateDecl', fields, location: location() };
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
StateFields
|
|
173
|
+
= head:StateField tail:(_ StateField)* {
|
|
174
|
+
return [head, ...tail.map(t => t[1])];
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
StateField
|
|
178
|
+
= name:Identifier _ ":" _ type:TypeAnnotation _ init:("=" _ Expression)? _ {
|
|
179
|
+
return {
|
|
180
|
+
name,
|
|
181
|
+
type,
|
|
182
|
+
init: init ? init[2] : null,
|
|
183
|
+
location: location()
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
/ name:Identifier _ "=" _ init:Expression _ {
|
|
187
|
+
return {
|
|
188
|
+
name,
|
|
189
|
+
type: null,
|
|
190
|
+
init,
|
|
191
|
+
location: location()
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
PlaybookDecl
|
|
196
|
+
= "playbook"i _ name:StringLiteral _ content:StringLiteral _ {
|
|
197
|
+
return { type: 'PlaybookDecl', name, content, location: location() };
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
ResilienceDecl
|
|
201
|
+
= "resilience"i _ name:StringLiteral _ "{" _ props:ResilienceProps _ "}" _ {
|
|
202
|
+
return { type: 'ResilienceDecl', name, properties: props, location: location() };
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
ResilienceProps
|
|
206
|
+
= head:ResilienceProp tail:(_ ResilienceProp)* {
|
|
207
|
+
return [head, ...tail.map(t => t[1])];
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
ResilienceProp
|
|
211
|
+
= name:Identifier _ "=" _ value:(Literal / Identifier) _ {
|
|
212
|
+
return { name, value, location: location() };
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// ============================================================
|
|
216
|
+
// Skill
|
|
217
|
+
// ============================================================
|
|
218
|
+
|
|
219
|
+
SkillDecl
|
|
220
|
+
= "Skill"i _ name:Identifier _ "{" _ body:SkillBody _ "}" _ {
|
|
221
|
+
// Extract affordance, functions, agents, teams from body
|
|
222
|
+
const affordance = body.find(item => item.type === 'AffordanceDecl');
|
|
223
|
+
const functions = body.filter(item => item.type === 'ExportFunction');
|
|
224
|
+
const agents = body.filter(item => item.type === 'AgentDecl');
|
|
225
|
+
const teams = body.filter(item => item.type === 'TeamDecl');
|
|
226
|
+
|
|
227
|
+
return {
|
|
228
|
+
type: 'SkillDecl',
|
|
229
|
+
name,
|
|
230
|
+
affordance: affordance ? affordance.content.value : null,
|
|
231
|
+
functions,
|
|
232
|
+
agents,
|
|
233
|
+
teams,
|
|
234
|
+
location: location()
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
SkillBody
|
|
239
|
+
= items:(SkillBodyItem)* {
|
|
240
|
+
return items;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
SkillBodyItem
|
|
244
|
+
= AffordanceDecl
|
|
245
|
+
/ AgentDecl
|
|
246
|
+
/ TeamDecl
|
|
247
|
+
/ ExportFunction
|
|
248
|
+
|
|
249
|
+
AffordanceDecl
|
|
250
|
+
= "affordance"i _ content:StringLiteral _ {
|
|
251
|
+
return { type: 'AffordanceDecl', content, location: location() };
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
ExportFunction
|
|
255
|
+
= "export"i _ isAsync:("async"i _)? "function"i _ name:Identifier _ "(" _ params:Parameters? _ ")" _ ":" _ returnType:TypeAnnotation _ "{" body:FunctionBody "}" _ {
|
|
256
|
+
return {
|
|
257
|
+
type: 'ExportFunction',
|
|
258
|
+
name,
|
|
259
|
+
isExport: true,
|
|
260
|
+
isAsync: !!isAsync,
|
|
261
|
+
params: params || [],
|
|
262
|
+
returnType,
|
|
263
|
+
body: { code: body },
|
|
264
|
+
location: location()
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// Capture function body as raw text (handles nested braces)
|
|
269
|
+
FunctionBody
|
|
270
|
+
= body:$((FunctionBodyChar)*) {
|
|
271
|
+
return body.trim();
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
FunctionBodyChar
|
|
275
|
+
= "{" FunctionBody "}" // Nested braces
|
|
276
|
+
/ [^{}] // Any character except braces
|
|
277
|
+
|
|
278
|
+
// ============================================================
|
|
279
|
+
// Statements
|
|
280
|
+
// ============================================================
|
|
281
|
+
|
|
282
|
+
Statement
|
|
283
|
+
= PlaybookStatement
|
|
284
|
+
/ VariableDeclaration
|
|
285
|
+
/ ConstDeclaration
|
|
286
|
+
/ IfStatement
|
|
287
|
+
/ ForStatement
|
|
288
|
+
/ WhileStatement
|
|
289
|
+
/ ReturnStatement
|
|
290
|
+
/ SendStatement
|
|
291
|
+
/ UsePlaybookStatement
|
|
292
|
+
/ ExpressionStatement
|
|
293
|
+
|
|
294
|
+
PlaybookStatement
|
|
295
|
+
= "playbook"i _ content:StringLiteral _ {
|
|
296
|
+
return { type: 'PlaybookStatement', content, location: location() };
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
VariableDeclaration
|
|
300
|
+
= "var"i _ name:Identifier _ ":" _ type:TypeAnnotation _ init:("=" _ Expression)? _ {
|
|
301
|
+
return {
|
|
302
|
+
type: 'VariableDeclaration',
|
|
303
|
+
name,
|
|
304
|
+
varType: type,
|
|
305
|
+
init: init ? init[2] : null,
|
|
306
|
+
location: location()
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
ConstDeclaration
|
|
311
|
+
= "const"i _ name:Identifier _ "=" _ value:Expression _ {
|
|
312
|
+
return { type: 'ConstDeclaration', name, value, location: location() };
|
|
313
|
+
}
|
|
314
|
+
/ "let"i _ name:Identifier _ "=" _ value:Expression _ {
|
|
315
|
+
return { type: 'ConstDeclaration', name, value, location: location() };
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
IfStatement
|
|
319
|
+
= "if"i _ cond:Expression _ "{" _ then:Statement* _ "}" _ alt:ElseClause? _ {
|
|
320
|
+
return { type: 'IfStatement', condition: cond, then, else: alt, location: location() };
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
ElseClause
|
|
324
|
+
= "else"i _ "{" _ body:Statement* _ "}" {
|
|
325
|
+
return body;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
ForStatement
|
|
329
|
+
= "for"i _ "(" _ decl:("const"i / "let"i / "var"i) _ id:Identifier _ "of"i _ expr:Expression _ ")" _ "{" _ body:Statement* _ "}" _ {
|
|
330
|
+
return { type: 'ForOfStatement', declaration: decl, id, expression: expr, body, location: location() };
|
|
331
|
+
}
|
|
332
|
+
/ "for"i _ "(" _ decl:("const"i / "let"i / "var"i) _ id:Identifier _ "in"i _ expr:Expression _ ")" _ "{" _ body:Statement* _ "}" _ {
|
|
333
|
+
return { type: 'ForInStatement', declaration: decl, id, expression: expr, body, location: location() };
|
|
334
|
+
}
|
|
335
|
+
/ "for"i _ "(" _ init:ForInit? _ ";" _ cond:Expression? _ ";" _ update:Expression? _ ")" _ "{" _ body:Statement* _ "}" _ {
|
|
336
|
+
return { type: 'ForStatement', init, condition: cond, update, body, location: location() };
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
ForInit
|
|
340
|
+
= VariableDeclaration
|
|
341
|
+
/ ConstDeclaration
|
|
342
|
+
/ Expression
|
|
343
|
+
|
|
344
|
+
WhileStatement
|
|
345
|
+
= "while"i _ cond:Expression _ "{" _ body:Statement* _ "}" _ {
|
|
346
|
+
return { type: 'WhileStatement', condition: cond, body, location: location() };
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
ReturnStatement
|
|
350
|
+
= "return"i _ value:Expression? _ {
|
|
351
|
+
return { type: 'ReturnStatement', value, location: location() };
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
SendStatement
|
|
355
|
+
= "await"i _ "send"i _ target:SendTarget _ args:CallArguments _ timeout:TimeoutClause? _ {
|
|
356
|
+
return { type: 'SendStatement', target, arguments: args, timeout, location: location() };
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
SendTarget
|
|
360
|
+
= base:PostfixExpression filters:SendFilter* {
|
|
361
|
+
return { base, filters, location: location() };
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
SendFilter
|
|
365
|
+
= "." "event"i "(" _ name:StringLiteral _ ")" {
|
|
366
|
+
return { type: 'EventFilter', event: name, location: location() };
|
|
367
|
+
}
|
|
368
|
+
/ "." "role"i "(" _ role:Identifier _ ")" {
|
|
369
|
+
return { type: 'RoleFilter', role, location: location() };
|
|
370
|
+
}
|
|
371
|
+
/ "." "any"i "(" _ ")" {
|
|
372
|
+
return { type: 'SelectionFilter', mode: 'any', location: location() };
|
|
373
|
+
}
|
|
374
|
+
/ "." "all"i "(" _ ")" {
|
|
375
|
+
return { type: 'SelectionFilter', mode: 'all', location: location() };
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
TimeoutClause
|
|
379
|
+
= "timeout"i _ value:Integer unit:TimeUnit {
|
|
380
|
+
return { value, unit, location: location() };
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
TimeUnit
|
|
384
|
+
= "ms"i / "s"i / "m"i / "h"i
|
|
385
|
+
|
|
386
|
+
UsePlaybookStatement
|
|
387
|
+
= "use"i _ "playbook"i _ name:(Identifier / StringLiteral) _ {
|
|
388
|
+
return { type: 'UsePlaybookStatement', name, location: location() };
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
ExpressionStatement
|
|
392
|
+
= expr:Expression _ {
|
|
393
|
+
return { type: 'ExpressionStatement', expression: expr, location: location() };
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
// ============================================================
|
|
397
|
+
// Expressions
|
|
398
|
+
// ============================================================
|
|
399
|
+
|
|
400
|
+
Expression
|
|
401
|
+
= AssignmentExpression
|
|
402
|
+
/ LogicalOrExpression
|
|
403
|
+
|
|
404
|
+
AssignmentExpression
|
|
405
|
+
= left:Identifier _ op:("=" / "+=" / "-=" / "*=" / "/=" / "%=") _ right:Expression {
|
|
406
|
+
return { type: 'AssignmentExpression', operator: op, left, right, location: location() };
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
LogicalOrExpression
|
|
410
|
+
= head:LogicalAndExpression tail:(_ ("||") _ LogicalAndExpression)* {
|
|
411
|
+
return buildBinaryExpression(head, tail);
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
LogicalAndExpression
|
|
415
|
+
= head:EqualityExpression tail:(_ ("&&") _ EqualityExpression)* {
|
|
416
|
+
return buildBinaryExpression(head, tail);
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
EqualityExpression
|
|
420
|
+
= head:RelationalExpression tail:(_ ("===" / "!==" / "==" / "!=") _ RelationalExpression)* {
|
|
421
|
+
return buildBinaryExpression(head, tail);
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
RelationalExpression
|
|
425
|
+
= head:AdditiveExpression tail:(_ ("<=" / ">=" / "<" / ">") _ AdditiveExpression)* {
|
|
426
|
+
return buildBinaryExpression(head, tail);
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
AdditiveExpression
|
|
430
|
+
= head:MultiplicativeExpression tail:(_ ("+" / "-") _ MultiplicativeExpression)* {
|
|
431
|
+
return buildBinaryExpression(head, tail);
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
MultiplicativeExpression
|
|
435
|
+
= head:UnaryExpression tail:(_ ("*" / "/" / "%") _ UnaryExpression)* {
|
|
436
|
+
return buildBinaryExpression(head, tail);
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
UnaryExpression
|
|
440
|
+
= AwaitExpression
|
|
441
|
+
/ NewExpression
|
|
442
|
+
/ op:("!" / "-") _ expr:UnaryExpression {
|
|
443
|
+
return { type: 'UnaryExpression', operator: op, argument: expr, location: location() };
|
|
444
|
+
}
|
|
445
|
+
/ PostfixExpression
|
|
446
|
+
|
|
447
|
+
NewExpression
|
|
448
|
+
= "new" _ callee:MemberOrPrimary args:CallArguments {
|
|
449
|
+
return { type: 'NewExpression', callee, arguments: args, location: location() };
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
// Member or Primary for new expressions (no call arguments included)
|
|
453
|
+
MemberOrPrimary
|
|
454
|
+
= base:PrimaryExpression props:PropertyAccessOnly+ {
|
|
455
|
+
return props.reduce((obj, acc) => ({
|
|
456
|
+
type: 'MemberExpression',
|
|
457
|
+
object: obj,
|
|
458
|
+
property: acc.property,
|
|
459
|
+
computed: acc.computed,
|
|
460
|
+
location: location()
|
|
461
|
+
}), base);
|
|
462
|
+
}
|
|
463
|
+
/ PrimaryExpression
|
|
464
|
+
|
|
465
|
+
PropertyAccessOnly
|
|
466
|
+
= "." _ prop:Identifier {
|
|
467
|
+
return { property: prop, computed: false };
|
|
468
|
+
}
|
|
469
|
+
/ "[" _ prop:Expression _ "]" {
|
|
470
|
+
return { property: prop, computed: true };
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
PostfixExpression
|
|
474
|
+
= ChainedExpression
|
|
475
|
+
/ PrimaryExpression
|
|
476
|
+
|
|
477
|
+
// Chained expressions support method calls and property access in any order
|
|
478
|
+
// Examples: obj.method(), obj.prop.method(), obj.method().prop, obj.method().method2()
|
|
479
|
+
ChainedExpression
|
|
480
|
+
= base:PrimaryExpression chain:ChainElement+ {
|
|
481
|
+
return chain.reduce((obj, element) => {
|
|
482
|
+
if (element.type === 'call') {
|
|
483
|
+
return { type: 'CallExpression', callee: obj, arguments: element.args, location: location() };
|
|
484
|
+
} else if (element.type === 'member') {
|
|
485
|
+
return { type: 'MemberExpression', object: obj, property: element.property, computed: element.computed, location: location() };
|
|
486
|
+
}
|
|
487
|
+
return obj;
|
|
488
|
+
}, base);
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
ChainElement
|
|
492
|
+
= "." _ prop:Identifier {
|
|
493
|
+
return { type: 'member', property: prop, computed: false };
|
|
494
|
+
}
|
|
495
|
+
/ "[" _ prop:Expression _ "]" {
|
|
496
|
+
return { type: 'member', property: prop, computed: true };
|
|
497
|
+
}
|
|
498
|
+
/ args:CallArguments {
|
|
499
|
+
return { type: 'call', args };
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
CallArguments
|
|
503
|
+
= "(" _ args:ArgumentList? _ ")" {
|
|
504
|
+
return args || [];
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
ArgumentList
|
|
508
|
+
= head:Expression tail:(_ "," _ Expression)* _ ","? {
|
|
509
|
+
return [head, ...tail.map(t => t[3])];
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
// Keep old MemberExpression for backwards compatibility (not used directly anymore)
|
|
513
|
+
MemberExpression
|
|
514
|
+
= object:PrimaryExpression props:PropertyAccess+ {
|
|
515
|
+
return props.reduce((obj, acc) => ({
|
|
516
|
+
type: 'MemberExpression',
|
|
517
|
+
object: obj,
|
|
518
|
+
property: acc.property,
|
|
519
|
+
computed: acc.computed,
|
|
520
|
+
location: location()
|
|
521
|
+
}), object);
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
PropertyAccess
|
|
525
|
+
= "." prop:Identifier {
|
|
526
|
+
return { property: prop, computed: false };
|
|
527
|
+
}
|
|
528
|
+
/ "[" _ prop:Expression _ "]" {
|
|
529
|
+
return { property: prop, computed: true };
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
PrimaryExpression
|
|
533
|
+
= ArrowFunction
|
|
534
|
+
/ Identifier
|
|
535
|
+
/ Literal
|
|
536
|
+
/ ObjectLiteral
|
|
537
|
+
/ ArrayLiteral
|
|
538
|
+
/ "(" _ expr:Expression _ ")" { return expr; }
|
|
539
|
+
|
|
540
|
+
AwaitExpression
|
|
541
|
+
= "await"i _ "send"i _ target:SendTarget _ args:CallArguments _ timeout:TimeoutClause? {
|
|
542
|
+
return { type: 'AwaitExpression', target, arguments: args, timeout, location: location() };
|
|
543
|
+
}
|
|
544
|
+
/ "await"i _ expr:PostfixExpression {
|
|
545
|
+
return { type: 'AwaitExpression', argument: expr, location: location() };
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
ArrowFunction
|
|
549
|
+
= "(" _ params:ParameterList? _ ")" _ "=>" _ body:ArrowBody {
|
|
550
|
+
return { type: 'ArrowFunction', params: params || [], body, location: location() };
|
|
551
|
+
}
|
|
552
|
+
/ param:Identifier _ "=>" _ body:ArrowBody {
|
|
553
|
+
return { type: 'ArrowFunction', params: [param], body, location: location() };
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
ParameterList
|
|
557
|
+
= head:Identifier tail:(_ "," _ Identifier)* {
|
|
558
|
+
return [head, ...tail.map(t => t[3])];
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
ArrowBody
|
|
562
|
+
= "{" _ stmts:Statement* _ "}" {
|
|
563
|
+
return { type: 'BlockStatement', statements: stmts, location: location() };
|
|
564
|
+
}
|
|
565
|
+
/ expr:Expression {
|
|
566
|
+
return expr;
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
// ============================================================
|
|
570
|
+
// Literals
|
|
571
|
+
// ============================================================
|
|
572
|
+
|
|
573
|
+
Literal
|
|
574
|
+
= MCPAddress
|
|
575
|
+
/ TemplateLiteral
|
|
576
|
+
/ StringLiteral
|
|
577
|
+
/ NumberLiteral
|
|
578
|
+
/ BooleanLiteral
|
|
579
|
+
/ NullLiteral
|
|
580
|
+
|
|
581
|
+
MCPAddress
|
|
582
|
+
= "mcp://" server:$([a-zA-Z0-9.-]+) "/" path:$([a-zA-Z0-9/_.-]*) {
|
|
583
|
+
return {
|
|
584
|
+
type: 'MCPAddress',
|
|
585
|
+
server,
|
|
586
|
+
path,
|
|
587
|
+
address: `mcp://${server}/${path}`,
|
|
588
|
+
location: location()
|
|
589
|
+
};
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
TemplateLiteral
|
|
593
|
+
= "`" parts:TemplatePart* "`" {
|
|
594
|
+
return { type: 'TemplateLiteral', parts, location: location() };
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
TemplatePart
|
|
598
|
+
= "${" _ expr:Expression _ "}" {
|
|
599
|
+
return { type: 'TemplateExpression', expression: expr, location: location() };
|
|
600
|
+
}
|
|
601
|
+
/ chars:TemplateChar+ {
|
|
602
|
+
return { type: 'TemplateString', value: chars.join(''), location: location() };
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
TemplateChar
|
|
606
|
+
= !("${" / "`" / "\\") char:. { return char; }
|
|
607
|
+
/ "\\" seq:EscapeSequence { return seq; }
|
|
608
|
+
|
|
609
|
+
StringLiteral
|
|
610
|
+
= "\"\"\"" content:$((!("\"\"\"") .)* ) "\"\"\"" {
|
|
611
|
+
return { type: 'StringLiteral', value: content.trim(), multiline: true, location: location() };
|
|
612
|
+
}
|
|
613
|
+
/ "\"" chars:DoubleStringChar* "\"" {
|
|
614
|
+
return { type: 'StringLiteral', value: chars.join(''), multiline: false, location: location() };
|
|
615
|
+
}
|
|
616
|
+
/ "'" chars:SingleStringChar* "'" {
|
|
617
|
+
return { type: 'StringLiteral', value: chars.join(''), multiline: false, location: location() };
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
DoubleStringChar
|
|
621
|
+
= !("\"" / "\\") char:. { return char; }
|
|
622
|
+
/ "\\" seq:EscapeSequence { return seq; }
|
|
623
|
+
|
|
624
|
+
SingleStringChar
|
|
625
|
+
= !("'" / "\\") char:. { return char; }
|
|
626
|
+
/ "\\" seq:EscapeSequence { return seq; }
|
|
627
|
+
|
|
628
|
+
EscapeSequence
|
|
629
|
+
= "n" { return "\n"; }
|
|
630
|
+
/ "t" { return "\t"; }
|
|
631
|
+
/ "r" { return "\r"; }
|
|
632
|
+
/ "\\" { return "\\"; }
|
|
633
|
+
/ "\"" { return "\""; }
|
|
634
|
+
/ "'" { return "'"; }
|
|
635
|
+
|
|
636
|
+
NumberLiteral
|
|
637
|
+
= value:Float {
|
|
638
|
+
return { type: 'NumberLiteral', value: parseFloat(value), location: location() };
|
|
639
|
+
}
|
|
640
|
+
/ value:Integer {
|
|
641
|
+
return { type: 'NumberLiteral', value: parseInt(value, 10), location: location() };
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
Float
|
|
645
|
+
= Integer "." Digit+ { return text(); }
|
|
646
|
+
|
|
647
|
+
Integer
|
|
648
|
+
= Digit+ { return text(); }
|
|
649
|
+
|
|
650
|
+
BooleanLiteral
|
|
651
|
+
= "true"i {
|
|
652
|
+
return { type: 'BooleanLiteral', value: true, location: location() };
|
|
653
|
+
}
|
|
654
|
+
/ "false"i {
|
|
655
|
+
return { type: 'BooleanLiteral', value: false, location: location() };
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
NullLiteral
|
|
659
|
+
= "null"i {
|
|
660
|
+
return { type: 'NullLiteral', value: null, location: location() };
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
ObjectLiteral
|
|
664
|
+
= "{" _ props:PropertyList? _ "}" {
|
|
665
|
+
return { type: 'ObjectLiteral', properties: props || [], location: location() };
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
PropertyList
|
|
669
|
+
= head:Property tail:(_ "," _ Property)* _ ","? {
|
|
670
|
+
return [head, ...tail.map(t => t[3])];
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
Property
|
|
674
|
+
= "..." _ expr:Expression {
|
|
675
|
+
return { type: 'SpreadProperty', argument: expr, location: location() };
|
|
676
|
+
}
|
|
677
|
+
/ key:(Identifier / StringLiteral / PropertyKey) _ ":" _ value:Expression {
|
|
678
|
+
return { key, value, location: location() };
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
PropertyKey
|
|
682
|
+
= name:$("$"? [a-zA-Z_][a-zA-Z0-9_]*) {
|
|
683
|
+
return { name, type: 'Identifier', location: location() };
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
ArrayLiteral
|
|
687
|
+
= "[" _ elements:ArgumentList? _ "]" {
|
|
688
|
+
return { type: 'ArrayLiteral', elements: elements || [], location: location() };
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
// ============================================================
|
|
692
|
+
// Types
|
|
693
|
+
// ============================================================
|
|
694
|
+
|
|
695
|
+
TypeAnnotation
|
|
696
|
+
= "Int"i { return { type: 'TypeAnnotation', name: 'Int', location: location() }; }
|
|
697
|
+
/ "String"i { return { type: 'TypeAnnotation', name: 'String', location: location() }; }
|
|
698
|
+
/ "Bool"i { return { type: 'TypeAnnotation', name: 'Bool', location: location() }; }
|
|
699
|
+
/ "Json"i { return { type: 'TypeAnnotation', name: 'Json', location: location() }; }
|
|
700
|
+
/ "Promise"i _ "<" _ inner:TypeAnnotation _ ">" {
|
|
701
|
+
return { type: 'TypeAnnotation', name: 'Promise', inner, location: location() };
|
|
702
|
+
}
|
|
703
|
+
/ name:Identifier {
|
|
704
|
+
return { type: 'TypeAnnotation', name: name.name, location: location() };
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
// ============================================================
|
|
708
|
+
// Parameters
|
|
709
|
+
// ============================================================
|
|
710
|
+
|
|
711
|
+
Parameters
|
|
712
|
+
= head:Parameter tail:(_ "," _ Parameter)* _ ","? {
|
|
713
|
+
return [head, ...tail.map(t => t[3])];
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
Parameter
|
|
717
|
+
= name:Identifier _ ":" _ type:TypeAnnotation {
|
|
718
|
+
return { name, type, location: location() };
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
// ============================================================
|
|
722
|
+
// Run Statement
|
|
723
|
+
// ============================================================
|
|
724
|
+
|
|
725
|
+
RunStatement
|
|
726
|
+
= "run"i _ target:MemberExpression args:CallArguments _ {
|
|
727
|
+
return { type: 'RunStatement', target, arguments: args, location: location() };
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
// ============================================================
|
|
731
|
+
// Identifiers
|
|
732
|
+
// ============================================================
|
|
733
|
+
|
|
734
|
+
Identifier
|
|
735
|
+
= !ReservedWord name:$([a-zA-Z_][a-zA-Z0-9_]*) {
|
|
736
|
+
return { type: 'Identifier', name, location: location() };
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
ReservedWord
|
|
740
|
+
= ("package" / "import" / "skill" / "role" / "can" / "Team" / "Agent" / "Skill" /
|
|
741
|
+
"uses" / "llm" / "default" / "on" / "state" / "playbook" / "resilience" /
|
|
742
|
+
"export" / "async" / "function" / "var" / "const" / "let" / "if" / "else" / "for" / "of" / "in" / "while" /
|
|
743
|
+
"return" / "await" / "send" / "timeout" / "use" / "run" /
|
|
744
|
+
"override" / "affordance" / "true" / "false" / "null") !IdentifierPart
|
|
745
|
+
|
|
746
|
+
IdentifierPart
|
|
747
|
+
= [a-zA-Z0-9_]
|
|
748
|
+
|
|
749
|
+
Digit
|
|
750
|
+
= [0-9]
|
|
751
|
+
|
|
752
|
+
// ============================================================
|
|
753
|
+
// Whitespace and Comments
|
|
754
|
+
// ============================================================
|
|
755
|
+
|
|
756
|
+
_
|
|
757
|
+
= (WhiteSpace / LineTerminator / Comment)*
|
|
758
|
+
|
|
759
|
+
WhiteSpace
|
|
760
|
+
= [ \t\r\n]
|
|
761
|
+
|
|
762
|
+
LineTerminator
|
|
763
|
+
= [\n\r]
|
|
764
|
+
|
|
765
|
+
Comment
|
|
766
|
+
= "//" (!LineTerminator .)*
|
|
767
|
+
/ "/*" (!"*/" .)* "*/"
|