@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.
Files changed (85) hide show
  1. package/QUICKSTART.md +89 -0
  2. package/README.md +545 -0
  3. package/examples/actions-demo.koi +177 -0
  4. package/examples/cache-test.koi +29 -0
  5. package/examples/calculator.koi +61 -0
  6. package/examples/clear-registry.js +33 -0
  7. package/examples/clear-registry.koi +30 -0
  8. package/examples/code-introspection-test.koi +149 -0
  9. package/examples/counter.koi +132 -0
  10. package/examples/delegation-test.koi +52 -0
  11. package/examples/directory-import-test.koi +84 -0
  12. package/examples/hello-world-claude.koi +52 -0
  13. package/examples/hello-world.koi +52 -0
  14. package/examples/hello.koi +24 -0
  15. package/examples/mcp-example.koi +70 -0
  16. package/examples/multi-event-handler-test.koi +144 -0
  17. package/examples/new-import-test.koi +89 -0
  18. package/examples/pipeline.koi +162 -0
  19. package/examples/registry-demo.koi +184 -0
  20. package/examples/registry-playbook-demo.koi +162 -0
  21. package/examples/registry-playbook-email-compositor-2.koi +140 -0
  22. package/examples/registry-playbook-email-compositor.koi +140 -0
  23. package/examples/sentiment.koi +90 -0
  24. package/examples/simple.koi +48 -0
  25. package/examples/skill-import-test.koi +76 -0
  26. package/examples/skills/advanced/index.koi +95 -0
  27. package/examples/skills/math-operations.koi +69 -0
  28. package/examples/skills/string-operations.koi +56 -0
  29. package/examples/task-chaining-demo.koi +244 -0
  30. package/examples/test-await.koi +22 -0
  31. package/examples/test-crypto-sha256.koi +196 -0
  32. package/examples/test-delegation.koi +41 -0
  33. package/examples/test-multi-team-routing.koi +258 -0
  34. package/examples/test-no-handler.koi +35 -0
  35. package/examples/test-npm-import.koi +67 -0
  36. package/examples/test-parse.koi +10 -0
  37. package/examples/test-peers-with-team.koi +59 -0
  38. package/examples/test-permissions-fail.koi +20 -0
  39. package/examples/test-permissions.koi +36 -0
  40. package/examples/test-simple-registry.koi +31 -0
  41. package/examples/test-typescript-import.koi +64 -0
  42. package/examples/test-uses-team-syntax.koi +25 -0
  43. package/examples/test-uses-team.koi +31 -0
  44. package/examples/utils/calculator.test.ts +144 -0
  45. package/examples/utils/calculator.ts +56 -0
  46. package/examples/utils/math-helpers.js +50 -0
  47. package/examples/utils/math-helpers.ts +55 -0
  48. package/examples/web-delegation-demo.koi +165 -0
  49. package/package.json +78 -0
  50. package/src/cli/koi.js +793 -0
  51. package/src/compiler/build-optimizer.js +447 -0
  52. package/src/compiler/cache-manager.js +274 -0
  53. package/src/compiler/import-resolver.js +369 -0
  54. package/src/compiler/parser.js +7542 -0
  55. package/src/compiler/transpiler.js +1105 -0
  56. package/src/compiler/typescript-transpiler.js +148 -0
  57. package/src/grammar/koi.pegjs +767 -0
  58. package/src/runtime/action-registry.js +172 -0
  59. package/src/runtime/actions/call-skill.js +45 -0
  60. package/src/runtime/actions/format.js +115 -0
  61. package/src/runtime/actions/print.js +42 -0
  62. package/src/runtime/actions/registry-delete.js +37 -0
  63. package/src/runtime/actions/registry-get.js +37 -0
  64. package/src/runtime/actions/registry-keys.js +33 -0
  65. package/src/runtime/actions/registry-search.js +34 -0
  66. package/src/runtime/actions/registry-set.js +50 -0
  67. package/src/runtime/actions/return.js +31 -0
  68. package/src/runtime/actions/send-message.js +58 -0
  69. package/src/runtime/actions/update-state.js +36 -0
  70. package/src/runtime/agent.js +1368 -0
  71. package/src/runtime/cli-logger.js +205 -0
  72. package/src/runtime/incremental-json-parser.js +201 -0
  73. package/src/runtime/index.js +33 -0
  74. package/src/runtime/llm-provider.js +1372 -0
  75. package/src/runtime/mcp-client.js +1171 -0
  76. package/src/runtime/planner.js +273 -0
  77. package/src/runtime/registry-backends/keyv-sqlite.js +215 -0
  78. package/src/runtime/registry-backends/local.js +260 -0
  79. package/src/runtime/registry.js +162 -0
  80. package/src/runtime/role.js +14 -0
  81. package/src/runtime/router.js +395 -0
  82. package/src/runtime/runtime.js +113 -0
  83. package/src/runtime/skill-selector.js +173 -0
  84. package/src/runtime/skill.js +25 -0
  85. 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
+ / "/*" (!"*/" .)* "*/"