@koi-language/koi 1.0.6 → 1.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.
Files changed (113) hide show
  1. package/README.md +4 -125
  2. package/examples/.build/agent-dialogue.ts +138 -0
  3. package/examples/.build/agent-dialogue.ts.map +1 -0
  4. package/examples/.build/chess.ts +77 -0
  5. package/examples/.build/chess.ts.map +1 -0
  6. package/examples/.build/delegation-test.ts +140 -0
  7. package/examples/.build/delegation-test.ts.map +1 -0
  8. package/examples/.build/dialog-demo.ts +77 -0
  9. package/examples/.build/dialog-demo.ts.map +1 -0
  10. package/examples/.build/hello-world.ts +77 -0
  11. package/examples/.build/hello-world.ts.map +1 -0
  12. package/examples/.build/lover-dialog-demo.ts +77 -0
  13. package/examples/.build/lover-dialog-demo.ts.map +1 -0
  14. package/examples/.build/package.json +3 -0
  15. package/examples/.build/registry-interactive-demo.ts +202 -0
  16. package/examples/.build/registry-interactive-demo.ts.map +1 -0
  17. package/examples/.build/registry-playbook-demo.ts +201 -0
  18. package/examples/.build/registry-playbook-demo.ts.map +1 -0
  19. package/examples/.build/tic-tac-toe.ts +77 -0
  20. package/examples/.build/tic-tac-toe.ts.map +1 -0
  21. package/examples/actions-demo.koi +8 -9
  22. package/examples/activists-dialogue.koi +75 -0
  23. package/examples/agent-dialogue.koi +66 -0
  24. package/examples/chess.koi +19 -0
  25. package/examples/counter.koi +20 -69
  26. package/examples/delegation-test.koi +16 -18
  27. package/examples/dialog-demo.koi +20 -0
  28. package/examples/hello-world.koi +7 -43
  29. package/examples/mcp-stdio-demo.koi +29 -0
  30. package/examples/memory-test.koi +49 -0
  31. package/examples/mobile-mcp-demo.koi +32 -0
  32. package/examples/multi-event-handler-test.koi +16 -18
  33. package/examples/pipeline.koi +15 -17
  34. package/examples/prompt-demo.koi +20 -0
  35. package/examples/{registry-playbook-email-compositor.koi → registry-interactive-demo.koi} +27 -27
  36. package/examples/registry-playbook-demo.koi +28 -28
  37. package/examples/skill-import-test.koi +7 -9
  38. package/examples/skills/.build/math-operations.ts +1656 -0
  39. package/examples/skills/.build/math-operations.ts.map +1 -0
  40. package/examples/skills/.build/package.json +3 -0
  41. package/examples/skills/.build/string-operations.ts +1643 -0
  42. package/examples/skills/.build/string-operations.ts.map +1 -0
  43. package/examples/skills/advanced/.build/index.ts +3223 -0
  44. package/examples/skills/advanced/.build/index.ts.map +1 -0
  45. package/examples/skills/advanced/.build/package.json +3 -0
  46. package/examples/skills/advanced/index.koi +3 -5
  47. package/examples/skills/math-operations.koi +1 -3
  48. package/examples/skills/string-operations.koi +1 -3
  49. package/examples/tic-tac-toe.koi +19 -0
  50. package/examples/utils/echo-mcp-server.js +141 -0
  51. package/examples/web-delegation-demo.koi +15 -17
  52. package/package.json +2 -1
  53. package/src/cli/koi.js +30 -41
  54. package/src/compiler/build-optimizer.js +204 -289
  55. package/src/compiler/cache-manager.js +1 -1
  56. package/src/compiler/import-resolver.js +5 -9
  57. package/src/compiler/parser.js +6072 -3476
  58. package/src/compiler/transpiler.js +346 -38
  59. package/src/grammar/koi.pegjs +302 -62
  60. package/src/runtime/actions/{format.js → call-llm.js} +37 -44
  61. package/src/runtime/actions/call-mcp.js +97 -0
  62. package/src/runtime/actions/if.js +179 -0
  63. package/src/runtime/actions/print.js +3 -1
  64. package/src/runtime/actions/prompt-user.js +75 -0
  65. package/src/runtime/actions/repeat.js +147 -0
  66. package/src/runtime/actions/shell.js +185 -0
  67. package/src/runtime/actions/while.js +205 -0
  68. package/src/runtime/agent.js +592 -178
  69. package/src/runtime/cli-display.js +26 -0
  70. package/src/runtime/cli-input.js +421 -0
  71. package/src/runtime/cli-logger.js +2 -5
  72. package/src/runtime/cli-markdown.js +61 -0
  73. package/src/runtime/cli-select.js +106 -0
  74. package/src/runtime/incremental-json-parser.js +27 -17
  75. package/src/runtime/index.js +1 -0
  76. package/src/runtime/llm-provider.js +1083 -572
  77. package/src/runtime/mcp-registry.js +141 -0
  78. package/src/runtime/mcp-stdio-client.js +334 -0
  79. package/src/runtime/planner.js +1 -1
  80. package/src/runtime/playbook-session.js +259 -0
  81. package/src/runtime/registry-backends/keyv-sqlite.js +1 -1
  82. package/src/runtime/registry-backends/local.js +1 -1
  83. package/src/runtime/router.js +22 -26
  84. package/src/runtime/runtime.js +7 -1
  85. package/examples/cache-test.koi +0 -29
  86. package/examples/calculator.koi +0 -61
  87. package/examples/clear-registry.js +0 -33
  88. package/examples/clear-registry.koi +0 -30
  89. package/examples/code-introspection-test.koi +0 -149
  90. package/examples/directory-import-test.koi +0 -84
  91. package/examples/hello-world-claude.koi +0 -52
  92. package/examples/hello.koi +0 -24
  93. package/examples/mcp-example.koi +0 -70
  94. package/examples/new-import-test.koi +0 -89
  95. package/examples/registry-demo.koi +0 -184
  96. package/examples/registry-playbook-email-compositor-2.koi +0 -140
  97. package/examples/sentiment.koi +0 -90
  98. package/examples/simple.koi +0 -48
  99. package/examples/task-chaining-demo.koi +0 -244
  100. package/examples/test-await.koi +0 -22
  101. package/examples/test-crypto-sha256.koi +0 -196
  102. package/examples/test-delegation.koi +0 -41
  103. package/examples/test-multi-team-routing.koi +0 -258
  104. package/examples/test-no-handler.koi +0 -35
  105. package/examples/test-npm-import.koi +0 -67
  106. package/examples/test-parse.koi +0 -10
  107. package/examples/test-peers-with-team.koi +0 -59
  108. package/examples/test-permissions-fail.koi +0 -20
  109. package/examples/test-permissions.koi +0 -36
  110. package/examples/test-simple-registry.koi +0 -31
  111. package/examples/test-typescript-import.koi +0 -64
  112. package/examples/test-uses-team-syntax.koi +0 -25
  113. package/examples/test-uses-team.koi +0 -31
@@ -28,29 +28,20 @@ Program
28
28
  }
29
29
 
30
30
  Declaration
31
- = PackageDecl
32
- / ImportDecl
31
+ = ImportDecl
33
32
  / RoleDecl
34
33
  / TeamDecl
35
34
  / AgentDecl
36
35
  / SkillDecl
36
+ / MCPDecl
37
37
  / RunStatement
38
38
 
39
- // ============================================================
40
- // Package
41
- // ============================================================
42
-
43
- PackageDecl
44
- = "package"i _ name:StringLiteral _ {
45
- return { type: 'PackageDecl', name, location: location() };
46
- }
47
-
48
39
  // ============================================================
49
40
  // Import (TypeScript/JavaScript style)
50
41
  // ============================================================
51
42
 
52
43
  ImportDecl
53
- = "import"i _ name:StringLiteral _ {
44
+ = "import" _ name:StringLiteral _ {
54
45
  return { type: 'ImportDecl', what: 'module', name, location: location() };
55
46
  }
56
47
 
@@ -59,7 +50,7 @@ ImportDecl
59
50
  // ============================================================
60
51
 
61
52
  RoleDecl
62
- = "role"i _ name:Identifier _ "{" _ caps:RoleCapabilities _ "}" _ {
53
+ = "role" _ name:Identifier _ "{" _ caps:RoleCapabilities _ "}" _ {
63
54
  return { type: 'RoleDecl', name, capabilities: caps, location: location() };
64
55
  }
65
56
 
@@ -69,7 +60,7 @@ RoleCapabilities
69
60
  }
70
61
 
71
62
  RoleCapability
72
- = "can"i _ name:Identifier {
63
+ = "can" _ name:Identifier {
73
64
  return { type: 'Capability', name, location: location() };
74
65
  }
75
66
 
@@ -78,12 +69,12 @@ RoleCapability
78
69
  // ============================================================
79
70
 
80
71
  TeamDecl
81
- = "Team"i _ name:Identifier _ override:TeamOverride? _ "{" _ members:TeamMembers _ "}" _ {
72
+ = "team" _ name:Identifier _ override:TeamOverride? _ "{" _ members:TeamMembers _ "}" _ {
82
73
  return { type: 'TeamDecl', name, override, members, location: location() };
83
74
  }
84
75
 
85
76
  TeamOverride
86
- = "override"i _ "{" _ overrides:TeamMembers _ "}" {
77
+ = "override" _ "{" _ overrides:TeamMembers _ "}" {
87
78
  return overrides;
88
79
  }
89
80
 
@@ -93,16 +84,25 @@ TeamMembers
93
84
  }
94
85
 
95
86
  TeamMember
96
- = name:Identifier _ "=" _ value:(MCPAddress / StringLiteral / Identifier) _ {
87
+ = name:Identifier _ (":" / "=") _ value:(MCPAddress / StringLiteral / Identifier) _ {
97
88
  return { name, value, location: location() };
98
89
  }
99
90
 
91
+ // ============================================================
92
+ // MCP (Model Context Protocol) server declaration
93
+ // ============================================================
94
+
95
+ MCPDecl
96
+ = "mcp" _ name:Identifier _ "=" _ config:ObjectLiteral _ {
97
+ return { type: 'MCPDecl', name, config, location: location() };
98
+ }
99
+
100
100
  // ============================================================
101
101
  // Agent
102
102
  // ============================================================
103
103
 
104
104
  AgentDecl
105
- = "Agent"i _ name:Identifier _ ":" _ role:Identifier _ "{" _ body:AgentBody _ "}" _ {
105
+ = "agent" _ name:Identifier _ ":" _ role:Identifier _ "{" _ body:AgentBody _ "}" _ {
106
106
  return { type: 'AgentDecl', name, role, body, location: location() };
107
107
  }
108
108
 
@@ -115,23 +115,35 @@ AgentBody
115
115
  AgentBodyItem
116
116
  = UsesSkill
117
117
  / UsesTeam
118
+ / UsesMCP
118
119
  / LLMConfig
120
+ / AmnesiaDecl
119
121
  / EventHandler
120
122
  / StateDecl
121
123
  / PlaybookDecl
122
124
  / ResilienceDecl
123
125
  / ExportFunction
124
126
 
127
+ AmnesiaDecl
128
+ = "amnesia" _ "=" _ value:BooleanLiteral _ {
129
+ return { type: 'AmnesiaDecl', value, location: location() };
130
+ }
131
+
125
132
  UsesSkill
126
- = "uses"i _ "skill"i _ names:IdentifierList _ {
133
+ = "uses" _ "skill" _ names:IdentifierList _ {
127
134
  return names.map(name => ({ type: 'UsesSkill', skill: name, location: location() }));
128
135
  }
129
136
 
130
137
  UsesTeam
131
- = "uses"i _ "team"i _ names:IdentifierList _ {
138
+ = "uses" _ "team" _ names:IdentifierList _ {
132
139
  return names.map(name => ({ type: 'UsesTeam', team: name, location: location() }));
133
140
  }
134
141
 
142
+ UsesMCP
143
+ = "uses" _ "mcp" _ names:IdentifierList _ {
144
+ return names.map(name => ({ type: 'UsesMCP', mcp: name, location: location() }));
145
+ }
146
+
135
147
  // Comma-separated list of identifiers
136
148
  IdentifierList
137
149
  = first:Identifier rest:(_ "," _ Identifier)* {
@@ -139,19 +151,19 @@ IdentifierList
139
151
  }
140
152
 
141
153
  LLMConfig
142
- = "llm"i _ "default"i _ "=" _ config:ObjectLiteral _ {
154
+ = "llm" _ "default" _ "=" _ config:ObjectLiteral _ {
143
155
  return { type: 'LLMConfig', config, location: location() };
144
156
  }
145
157
 
146
158
  EventHandler
147
- = "on"i _ event:HandlerName _ "(" _ params:Parameters? _ ")" _ "{" _ body:Statement* _ "}" _ {
159
+ = "on" _ event:HandlerName _ "(" _ params:Parameters? _ ")" _ "{" _ body:Statement* _ "}" _ {
148
160
  return { type: 'EventHandler', event, params: params || [], body, location: location() };
149
161
  }
150
162
 
151
163
  HandlerName
152
164
  = 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',
165
+ const reserved = ['run', 'import', 'skill', 'role', 'can', 'team', 'agent',
166
+ 'uses', 'llm', 'default', 'on', 'state', 'playbook', 'resilience', 'amnesia', 'mcp',
155
167
  'export', 'async', 'function', 'var', 'const', 'let', 'if', 'else', 'for', 'of', 'in', 'while',
156
168
  'return', 'await', 'send', 'timeout', 'use', 'override', 'affordance',
157
169
  'true', 'false', 'null'];
@@ -165,7 +177,7 @@ HandlerName
165
177
  }
166
178
 
167
179
  StateDecl
168
- = "state"i _ "{" _ fields:StateFields _ "}" _ {
180
+ = "state" _ "{" _ fields:StateFields _ "}" _ {
169
181
  return { type: 'StateDecl', fields, location: location() };
170
182
  }
171
183
 
@@ -193,12 +205,12 @@ StateField
193
205
  }
194
206
 
195
207
  PlaybookDecl
196
- = "playbook"i _ name:StringLiteral _ content:StringLiteral _ {
208
+ = "playbook" _ name:StringLiteral _ content:StringLiteral _ {
197
209
  return { type: 'PlaybookDecl', name, content, location: location() };
198
210
  }
199
211
 
200
212
  ResilienceDecl
201
- = "resilience"i _ name:StringLiteral _ "{" _ props:ResilienceProps _ "}" _ {
213
+ = "resilience" _ name:StringLiteral _ "{" _ props:ResilienceProps _ "}" _ {
202
214
  return { type: 'ResilienceDecl', name, properties: props, location: location() };
203
215
  }
204
216
 
@@ -217,12 +229,14 @@ ResilienceProp
217
229
  // ============================================================
218
230
 
219
231
  SkillDecl
220
- = "Skill"i _ name:Identifier _ "{" _ body:SkillBody _ "}" _ {
221
- // Extract affordance, functions, agents, teams from body
232
+ = "skill" _ name:Identifier _ "{" _ body:SkillBody _ "}" _ {
233
+ // Extract affordance, functions, agents, teams, constants, variables from body
222
234
  const affordance = body.find(item => item.type === 'AffordanceDecl');
223
235
  const functions = body.filter(item => item.type === 'ExportFunction');
224
236
  const agents = body.filter(item => item.type === 'AgentDecl');
225
237
  const teams = body.filter(item => item.type === 'TeamDecl');
238
+ const constants = body.filter(item => item.type === 'SkillConstDeclaration');
239
+ const variables = body.filter(item => item.type === 'SkillVariableDeclaration');
226
240
 
227
241
  return {
228
242
  type: 'SkillDecl',
@@ -231,6 +245,8 @@ SkillDecl
231
245
  functions,
232
246
  agents,
233
247
  teams,
248
+ constants,
249
+ variables,
234
250
  location: location()
235
251
  };
236
252
  }
@@ -244,15 +260,116 @@ SkillBodyItem
244
260
  = AffordanceDecl
245
261
  / AgentDecl
246
262
  / TeamDecl
263
+ / SkillConstDeclaration
264
+ / SkillVariableDeclaration
247
265
  / ExportFunction
266
+ / NonExportFunction
248
267
 
249
268
  AffordanceDecl
250
- = "affordance"i _ content:StringLiteral _ {
269
+ = "affordance" _ content:StringLiteral _ {
251
270
  return { type: 'AffordanceDecl', content, location: location() };
252
271
  }
253
272
 
273
+ SkillConstDeclaration
274
+ = "const"i _ pattern:DestructuringPattern _ typeAnnotation:(":" _ TypeAnnotation)? _ "=" _ value:Expression _ {
275
+ return {
276
+ type: 'SkillConstDeclaration',
277
+ pattern,
278
+ typeAnnotation: typeAnnotation ? typeAnnotation[2] : null,
279
+ value,
280
+ location: location()
281
+ };
282
+ }
283
+ / "const"i _ name:Identifier _ typeAnnotation:(":" _ TypeAnnotation)? _ "=" _ value:Expression _ {
284
+ return {
285
+ type: 'SkillConstDeclaration',
286
+ pattern: { type: 'Identifier', name: name.name },
287
+ typeAnnotation: typeAnnotation ? typeAnnotation[2] : null,
288
+ value,
289
+ location: location()
290
+ };
291
+ }
292
+
293
+ SkillVariableDeclaration
294
+ = "let"i _ pattern:DestructuringPattern _ typeAnnotation:(":" _ TypeAnnotation)? _ init:("=" _ Expression)? _ {
295
+ return {
296
+ type: 'SkillVariableDeclaration',
297
+ pattern,
298
+ typeAnnotation: typeAnnotation ? typeAnnotation[2] : null,
299
+ init: init ? init[2] : null,
300
+ location: location()
301
+ };
302
+ }
303
+ / "let"i _ name:Identifier _ typeAnnotation:(":" _ TypeAnnotation)? _ init:("=" _ Expression)? _ {
304
+ return {
305
+ type: 'SkillVariableDeclaration',
306
+ pattern: { type: 'Identifier', name: name.name },
307
+ typeAnnotation: typeAnnotation ? typeAnnotation[2] : null,
308
+ init: init ? init[2] : null,
309
+ location: location()
310
+ };
311
+ }
312
+
313
+ DestructuringPattern
314
+ = ObjectDestructuringPattern
315
+ / ArrayDestructuringPattern
316
+
317
+ ObjectDestructuringPattern
318
+ = "{" _ props:DestructuringPropertyList _ "}" {
319
+ return { type: 'ObjectPattern', properties: props };
320
+ }
321
+
322
+ DestructuringPropertyList
323
+ = head:DestructuringProperty tail:(_ "," _ DestructuringProperty)* {
324
+ return [head, ...tail.map(t => t[3])];
325
+ }
326
+
327
+ DestructuringProperty
328
+ = key:Identifier _ ":" _ value:Identifier {
329
+ return { key: key.name, value: value.name };
330
+ }
331
+ / name:Identifier {
332
+ return { key: name.name, value: name.name };
333
+ }
334
+
335
+ ArrayDestructuringPattern
336
+ = "[" _ elements:DestructuringElementList _ "]" {
337
+ return { type: 'ArrayPattern', elements };
338
+ }
339
+
340
+ DestructuringElementList
341
+ = head:Identifier tail:(_ "," _ Identifier)* {
342
+ return [head.name, ...tail.map(t => t[3].name)];
343
+ }
344
+
345
+ NonExportFunction
346
+ = isAsync:("async"i _)? "function"i _ name:Identifier _ "(" _ params:Parameters? _ ")" _ ":" _ returnType:TypeAnnotation _ "{" body:FunctionBody "}" _ {
347
+ return {
348
+ type: 'ExportFunction',
349
+ name,
350
+ isExport: false,
351
+ isAsync: !!isAsync,
352
+ params: params || [],
353
+ returnType,
354
+ body: { code: body },
355
+ location: location()
356
+ };
357
+ }
358
+ / isAsync:("async"i _)? "function"i _ name:Identifier _ "(" _ params:Parameters? _ ")" _ "{" body:FunctionBody "}" _ {
359
+ return {
360
+ type: 'ExportFunction',
361
+ name,
362
+ isExport: false,
363
+ isAsync: !!isAsync,
364
+ params: params || [],
365
+ returnType: null,
366
+ body: { code: body },
367
+ location: location()
368
+ };
369
+ }
370
+
254
371
  ExportFunction
255
- = "export"i _ isAsync:("async"i _)? "function"i _ name:Identifier _ "(" _ params:Parameters? _ ")" _ ":" _ returnType:TypeAnnotation _ "{" body:FunctionBody "}" _ {
372
+ = "export" _ isAsync:("async"i _)? "function"i _ name:Identifier _ "(" _ params:Parameters? _ ")" _ ":" _ returnType:TypeAnnotation _ "{" body:FunctionBody "}" _ {
256
373
  return {
257
374
  type: 'ExportFunction',
258
375
  name,
@@ -283,16 +400,18 @@ Statement
283
400
  = PlaybookStatement
284
401
  / VariableDeclaration
285
402
  / ConstDeclaration
403
+ / TryStatement
286
404
  / IfStatement
287
405
  / ForStatement
288
406
  / WhileStatement
289
407
  / ReturnStatement
408
+ / ThrowStatement
290
409
  / SendStatement
291
410
  / UsePlaybookStatement
292
411
  / ExpressionStatement
293
412
 
294
413
  PlaybookStatement
295
- = "playbook"i _ content:StringLiteral _ {
414
+ = "playbook" _ content:StringLiteral _ {
296
415
  return { type: 'PlaybookStatement', content, location: location() };
297
416
  }
298
417
 
@@ -312,7 +431,7 @@ ConstDeclaration
312
431
  return { type: 'ConstDeclaration', name, value, location: location() };
313
432
  }
314
433
  / "let"i _ name:Identifier _ "=" _ value:Expression _ {
315
- return { type: 'ConstDeclaration', name, value, location: location() };
434
+ return { type: 'VariableDeclaration', name, init: value, varType: null, location: location() };
316
435
  }
317
436
 
318
437
  IfStatement
@@ -325,6 +444,23 @@ ElseClause
325
444
  return body;
326
445
  }
327
446
 
447
+ TryStatement
448
+ = "try"i _ "{" _ body:Statement* _ "}" _ handler:CatchClause? _ finalizer:FinallyClause? _ &{
449
+ return !!(handler || finalizer);
450
+ } {
451
+ return { type: 'TryStatement', body, handler, finalizer, location: location() };
452
+ }
453
+
454
+ CatchClause
455
+ = "catch"i _ "(" _ param:Identifier _ ")" _ "{" _ body:Statement* _ "}" {
456
+ return { type: 'CatchClause', param, body, location: location() };
457
+ }
458
+
459
+ FinallyClause
460
+ = "finally"i _ "{" _ body:Statement* _ "}" {
461
+ return body;
462
+ }
463
+
328
464
  ForStatement
329
465
  = "for"i _ "(" _ decl:("const"i / "let"i / "var"i) _ id:Identifier _ "of"i _ expr:Expression _ ")" _ "{" _ body:Statement* _ "}" _ {
330
466
  return { type: 'ForOfStatement', declaration: decl, id, expression: expr, body, location: location() };
@@ -351,27 +487,32 @@ ReturnStatement
351
487
  return { type: 'ReturnStatement', value, location: location() };
352
488
  }
353
489
 
490
+ ThrowStatement
491
+ = "throw"i _ value:Expression _ {
492
+ return { type: 'ThrowStatement', argument: value, location: location() };
493
+ }
494
+
354
495
  SendStatement
355
496
  = "await"i _ "send"i _ target:SendTarget _ args:CallArguments _ timeout:TimeoutClause? _ {
356
497
  return { type: 'SendStatement', target, arguments: args, timeout, location: location() };
357
498
  }
358
499
 
359
500
  SendTarget
360
- = base:PostfixExpression filters:SendFilter* {
501
+ = base:PrimaryExpression filters:SendFilter* {
361
502
  return { base, filters, location: location() };
362
503
  }
363
504
 
364
505
  SendFilter
365
- = "." "event"i "(" _ name:StringLiteral _ ")" {
506
+ = _ "." "event"i "(" _ name:StringLiteral _ ")" {
366
507
  return { type: 'EventFilter', event: name, location: location() };
367
508
  }
368
- / "." "role"i "(" _ role:Identifier _ ")" {
509
+ / _ "." "role"i "(" _ role:Identifier _ ")" {
369
510
  return { type: 'RoleFilter', role, location: location() };
370
511
  }
371
- / "." "any"i "(" _ ")" {
512
+ / _ "." "any"i "(" _ ")" {
372
513
  return { type: 'SelectionFilter', mode: 'any', location: location() };
373
514
  }
374
- / "." "all"i "(" _ ")" {
515
+ / _ "." "all"i "(" _ ")" {
375
516
  return { type: 'SelectionFilter', mode: 'all', location: location() };
376
517
  }
377
518
 
@@ -384,7 +525,7 @@ TimeUnit
384
525
  = "ms"i / "s"i / "m"i / "h"i
385
526
 
386
527
  UsePlaybookStatement
387
- = "use"i _ "playbook"i _ name:(Identifier / StringLiteral) _ {
528
+ = "use" _ "playbook" _ name:(Identifier / StringLiteral) _ {
388
529
  return { type: 'UsePlaybookStatement', name, location: location() };
389
530
  }
390
531
 
@@ -399,13 +540,23 @@ ExpressionStatement
399
540
 
400
541
  Expression
401
542
  = AssignmentExpression
543
+ / ConditionalExpression
544
+
545
+ ConditionalExpression
546
+ = test:LogicalOrExpression _ "?" _ consequent:Expression _ ":" _ alternate:Expression {
547
+ return { type: 'ConditionalExpression', test, consequent, alternate, location: location() };
548
+ }
402
549
  / LogicalOrExpression
403
550
 
404
551
  AssignmentExpression
405
- = left:Identifier _ op:("=" / "+=" / "-=" / "*=" / "/=" / "%=") _ right:Expression {
552
+ = left:AssignmentTarget _ op:("=" / "+=" / "-=" / "*=" / "/=" / "%=") _ right:Expression {
406
553
  return { type: 'AssignmentExpression', operator: op, left, right, location: location() };
407
554
  }
408
555
 
556
+ AssignmentTarget
557
+ = ChainedExpression
558
+ / Identifier
559
+
409
560
  LogicalOrExpression
410
561
  = head:LogicalAndExpression tail:(_ ("||") _ LogicalAndExpression)* {
411
562
  return buildBinaryExpression(head, tail);
@@ -422,7 +573,7 @@ EqualityExpression
422
573
  }
423
574
 
424
575
  RelationalExpression
425
- = head:AdditiveExpression tail:(_ ("<=" / ">=" / "<" / ">") _ AdditiveExpression)* {
576
+ = head:AdditiveExpression tail:(_ ("<=" / ">=" / "<" / ">" / "instanceof"i) _ AdditiveExpression)* {
426
577
  return buildBinaryExpression(head, tail);
427
578
  }
428
579
 
@@ -480,23 +631,32 @@ ChainedExpression
480
631
  = base:PrimaryExpression chain:ChainElement+ {
481
632
  return chain.reduce((obj, element) => {
482
633
  if (element.type === 'call') {
483
- return { type: 'CallExpression', callee: obj, arguments: element.args, location: location() };
634
+ return { type: 'CallExpression', callee: obj, arguments: element.args, optional: element.optional, location: location() };
484
635
  } else if (element.type === 'member') {
485
- return { type: 'MemberExpression', object: obj, property: element.property, computed: element.computed, location: location() };
636
+ return { type: 'MemberExpression', object: obj, property: element.property, computed: element.computed, optional: element.optional, location: location() };
486
637
  }
487
638
  return obj;
488
639
  }, base);
489
640
  }
490
641
 
491
642
  ChainElement
492
- = "." _ prop:Identifier {
493
- return { type: 'member', property: prop, computed: false };
643
+ = "?." _ prop:PropertyIdentifier {
644
+ return { type: 'member', property: prop, computed: false, optional: true };
645
+ }
646
+ / "." _ prop:PropertyIdentifier {
647
+ return { type: 'member', property: prop, computed: false, optional: false };
648
+ }
649
+ / "?.[" _ prop:Expression _ "]" {
650
+ return { type: 'member', property: prop, computed: true, optional: true };
494
651
  }
495
652
  / "[" _ prop:Expression _ "]" {
496
- return { type: 'member', property: prop, computed: true };
653
+ return { type: 'member', property: prop, computed: false, optional: false };
654
+ }
655
+ / "?." _ args:CallArguments {
656
+ return { type: 'call', args, optional: true };
497
657
  }
498
658
  / args:CallArguments {
499
- return { type: 'call', args };
659
+ return { type: 'call', args, optional: false };
500
660
  }
501
661
 
502
662
  CallArguments
@@ -546,11 +706,11 @@ AwaitExpression
546
706
  }
547
707
 
548
708
  ArrowFunction
549
- = "(" _ params:ParameterList? _ ")" _ "=>" _ body:ArrowBody {
550
- return { type: 'ArrowFunction', params: params || [], body, location: location() };
709
+ = isAsync:("async"i _)? "(" _ params:ParameterList? _ ")" _ "=>" _ body:ArrowBody {
710
+ return { type: 'ArrowFunction', params: params || [], body, isAsync: !!isAsync, location: location() };
551
711
  }
552
- / param:Identifier _ "=>" _ body:ArrowBody {
553
- return { type: 'ArrowFunction', params: [param], body, location: location() };
712
+ / isAsync:("async"i _)? param:Identifier _ "=>" _ body:ArrowBody {
713
+ return { type: 'ArrowFunction', params: [param], body, isAsync: !!isAsync, location: location() };
554
714
  }
555
715
 
556
716
  ParameterList
@@ -574,6 +734,7 @@ Literal
574
734
  = MCPAddress
575
735
  / TemplateLiteral
576
736
  / StringLiteral
737
+ / RegexLiteral
577
738
  / NumberLiteral
578
739
  / BooleanLiteral
579
740
  / NullLiteral
@@ -625,6 +786,21 @@ SingleStringChar
625
786
  = !("'" / "\\") char:. { return char; }
626
787
  / "\\" seq:EscapeSequence { return seq; }
627
788
 
789
+ RegexLiteral
790
+ = "/" pattern:RegexPattern "/" flags:RegexFlags? {
791
+ return { type: 'RegexLiteral', pattern, flags: flags || '', location: location() };
792
+ }
793
+
794
+ RegexPattern
795
+ = chars:RegexChar* { return chars.join(''); }
796
+
797
+ RegexChar
798
+ = "\\" char:. { return "\\" + char; } // Escaped character (including \/)
799
+ / ![/\n\r] char:. { return char; } // Any character except / and newlines
800
+
801
+ RegexFlags
802
+ = flags:$[gimsuvy]+ { return flags; }
803
+
628
804
  EscapeSequence
629
805
  = "n" { return "\n"; }
630
806
  / "t" { return "\t"; }
@@ -693,13 +869,66 @@ ArrayLiteral
693
869
  // ============================================================
694
870
 
695
871
  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 _ ">" {
872
+ = UnionType
873
+ / PostfixType
874
+
875
+ UnionType
876
+ = head:PostfixType tail:(_ "|" _ PostfixType)+ {
877
+ return { type: 'UnionType', types: [head, ...tail.map(t => t[3])], location: location() };
878
+ }
879
+
880
+ PostfixType
881
+ = base:PrimaryType suffixes:(_ "[" _ "]")+ {
882
+ // Apply array type for each []
883
+ return suffixes.reduce((type) => {
884
+ return { type: 'ArrayTypeAnnotation', elementType: type, location: location() };
885
+ }, base);
886
+ }
887
+ / PrimaryType
888
+
889
+ PrimaryType
890
+ = PromiseType
891
+ / ArrayTypeAnnotation
892
+ / ObjectTypeAnnotation
893
+ / PrimitiveType
894
+
895
+ ObjectTypeAnnotation
896
+ = "{" _ props:TypePropertyList _ "}" {
897
+ return { type: 'ObjectTypeAnnotation', properties: props, location: location() };
898
+ }
899
+
900
+ TypePropertyList
901
+ = head:TypeProperty tail:(_ "," _ TypeProperty)* _ ","? {
902
+ return [head, ...tail.map(t => t[3])];
903
+ }
904
+
905
+ TypeProperty
906
+ = name:PropertyIdentifier _ optional:"?"? _ ":" _ type:TypeAnnotation {
907
+ return { name: name.name, type, optional: !!optional };
908
+ }
909
+
910
+ ArrayTypeAnnotation
911
+ = "Array"i _ "<" _ elem:TypeAnnotation _ ">" {
912
+ return { type: 'ArrayTypeAnnotation', elementType: elem, location: location() };
913
+ }
914
+
915
+ PromiseType
916
+ = "Promise"i _ "<" _ inner:TypeAnnotation _ ">" {
701
917
  return { type: 'TypeAnnotation', name: 'Promise', inner, location: location() };
702
918
  }
919
+
920
+ PrimitiveType
921
+ = "boolean"i !IdentifierPart { return { type: 'BooleanType', location: location() }; }
922
+ / "number"i !IdentifierPart { return { type: 'NumberType', location: location() }; }
923
+ / "string"i !IdentifierPart { return { type: 'StringType', location: location() }; }
924
+ / "void"i !IdentifierPart { return { type: 'VoidType', location: location() }; }
925
+ / "any"i !IdentifierPart { return { type: 'AnyType', location: location() }; }
926
+ / "null"i !IdentifierPart { return { type: 'NullType', location: location() }; }
927
+ / "undefined"i !IdentifierPart { return { type: 'UndefinedType', location: location() }; }
928
+ / "Int"i !IdentifierPart { return { type: 'TypeAnnotation', name: 'Int', location: location() }; }
929
+ / "String"i !IdentifierPart { return { type: 'TypeAnnotation', name: 'String', location: location() }; }
930
+ / "Bool"i !IdentifierPart { return { type: 'TypeAnnotation', name: 'Bool', location: location() }; }
931
+ / "Json"i !IdentifierPart { return { type: 'TypeAnnotation', name: 'Json', location: location() }; }
703
932
  / name:Identifier {
704
933
  return { type: 'TypeAnnotation', name: name.name, location: location() };
705
934
  }
@@ -714,8 +943,11 @@ Parameters
714
943
  }
715
944
 
716
945
  Parameter
717
- = name:Identifier _ ":" _ type:TypeAnnotation {
718
- return { name, type, location: location() };
946
+ = name:Identifier _ ":" _ type:TypeAnnotation _ defaultValue:("=" _ Expression)? {
947
+ return { name, type, default: defaultValue ? defaultValue[2] : null, location: location() };
948
+ }
949
+ / name:Identifier {
950
+ return { name, type: null, default: null, location: location() };
719
951
  }
720
952
 
721
953
  // ============================================================
@@ -723,7 +955,7 @@ Parameter
723
955
  // ============================================================
724
956
 
725
957
  RunStatement
726
- = "run"i _ target:MemberExpression args:CallArguments _ {
958
+ = "run" _ target:MemberExpression args:CallArguments _ {
727
959
  return { type: 'RunStatement', target, arguments: args, location: location() };
728
960
  }
729
961
 
@@ -736,12 +968,20 @@ Identifier
736
968
  return { type: 'Identifier', name, location: location() };
737
969
  }
738
970
 
971
+ // PropertyIdentifier: allows reserved words as property names (after .)
972
+ // Examples: obj.state, obj.default, this.state
973
+ PropertyIdentifier
974
+ = name:$([a-zA-Z_][a-zA-Z0-9_]*) {
975
+ return { type: 'Identifier', name, location: location() };
976
+ }
977
+
739
978
  ReservedWord
740
- = ("package" / "import" / "skill" / "role" / "can" / "Team" / "Agent" / "Skill" /
741
- "uses" / "llm" / "default" / "on" / "state" / "playbook" / "resilience" /
979
+ = ("import" / "skill" / "role" / "can" / "team" / "agent" / "skill" /
980
+ "uses" / "llm" / "default" / "on" / "state" / "playbook" / "resilience" / "mcp" /
742
981
  "export" / "async" / "function" / "var" / "const" / "let" / "if" / "else" / "for" / "of" / "in" / "while" /
982
+ "try" / "catch" / "finally" / "throw" / "instanceof" /
743
983
  "return" / "await" / "send" / "timeout" / "use" / "run" /
744
- "override" / "affordance" / "true" / "false" / "null") !IdentifierPart
984
+ "override" / "affordance" / "amnesia" / "true" / "false" / "null") !IdentifierPart
745
985
 
746
986
  IdentifierPart
747
987
  = [a-zA-Z0-9_]