agentlang 0.0.67 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/out/api/http.d.ts.map +1 -1
  2. package/out/api/http.js +2 -1
  3. package/out/api/http.js.map +1 -1
  4. package/out/cli/main.d.ts.map +1 -1
  5. package/out/cli/main.js +7 -1
  6. package/out/cli/main.js.map +1 -1
  7. package/out/language/generated/ast.d.ts +1 -1
  8. package/out/language/generated/ast.d.ts.map +1 -1
  9. package/out/language/generated/ast.js +1 -1
  10. package/out/language/generated/ast.js.map +1 -1
  11. package/out/language/generated/grammar.js +1 -1
  12. package/out/language/main.cjs +2 -2
  13. package/out/language/main.cjs.map +2 -2
  14. package/out/runtime/agents/common.d.ts +0 -7
  15. package/out/runtime/agents/common.d.ts.map +1 -1
  16. package/out/runtime/agents/common.js +0 -34
  17. package/out/runtime/agents/common.js.map +1 -1
  18. package/out/runtime/agents/flows.d.ts +7 -0
  19. package/out/runtime/agents/flows.d.ts.map +1 -0
  20. package/out/runtime/agents/flows.js +33 -0
  21. package/out/runtime/agents/flows.js.map +1 -0
  22. package/out/runtime/defs.d.ts +58 -0
  23. package/out/runtime/defs.d.ts.map +1 -1
  24. package/out/runtime/defs.js +172 -0
  25. package/out/runtime/defs.js.map +1 -1
  26. package/out/runtime/exec-graph.d.ts +17 -0
  27. package/out/runtime/exec-graph.d.ts.map +1 -0
  28. package/out/runtime/exec-graph.js +434 -0
  29. package/out/runtime/exec-graph.js.map +1 -0
  30. package/out/runtime/interpreter.d.ts +38 -3
  31. package/out/runtime/interpreter.d.ts.map +1 -1
  32. package/out/runtime/interpreter.js +167 -60
  33. package/out/runtime/interpreter.js.map +1 -1
  34. package/out/runtime/loader.d.ts.map +1 -1
  35. package/out/runtime/loader.js +120 -2
  36. package/out/runtime/loader.js.map +1 -1
  37. package/out/runtime/module.d.ts +3 -0
  38. package/out/runtime/module.d.ts.map +1 -1
  39. package/out/runtime/module.js +35 -12
  40. package/out/runtime/module.js.map +1 -1
  41. package/out/runtime/modules/ai.d.ts +21 -2
  42. package/out/runtime/modules/ai.d.ts.map +1 -1
  43. package/out/runtime/modules/ai.js +56 -3
  44. package/out/runtime/modules/ai.js.map +1 -1
  45. package/out/runtime/resolvers/interface.d.ts +1 -0
  46. package/out/runtime/resolvers/interface.d.ts.map +1 -1
  47. package/out/runtime/resolvers/interface.js +5 -0
  48. package/out/runtime/resolvers/interface.js.map +1 -1
  49. package/out/utils/runtime.d.ts +1 -0
  50. package/out/utils/runtime.d.ts.map +1 -1
  51. package/out/utils/runtime.js +9 -0
  52. package/out/utils/runtime.js.map +1 -1
  53. package/package.json +34 -52
  54. package/src/api/http.ts +2 -1
  55. package/src/cli/main.ts +8 -1
  56. package/src/language/agentlang.langium +3 -2
  57. package/src/language/generated/ast.ts +2 -2
  58. package/src/language/generated/grammar.ts +1 -1
  59. package/src/runtime/agents/common.ts +0 -41
  60. package/src/runtime/agents/flows.ts +38 -0
  61. package/src/runtime/defs.ts +210 -0
  62. package/src/runtime/exec-graph.ts +518 -0
  63. package/src/runtime/interpreter.ts +202 -66
  64. package/src/runtime/loader.ts +124 -2
  65. package/src/runtime/module.ts +36 -12
  66. package/src/runtime/modules/ai.ts +102 -5
  67. package/src/runtime/resolvers/interface.ts +5 -0
  68. package/src/utils/runtime.ts +10 -0
@@ -20,6 +20,7 @@ import {
20
20
  Pattern,
21
21
  Purge,
22
22
  RelationshipPattern,
23
+ Return,
23
24
  RuntimeHint,
24
25
  SelectIntoEntry,
25
26
  SelectIntoSpec,
@@ -55,7 +56,6 @@ import {
55
56
  DefaultModuleName,
56
57
  escapeFqName,
57
58
  escapeQueryName,
58
- escapeSpecialChars,
59
59
  fqNameFromPath,
60
60
  isFqName,
61
61
  isPath,
@@ -90,7 +90,7 @@ import {
90
90
  import { invokeModuleFn } from './jsmodules.js';
91
91
  import { invokeOpenApiEvent, isOpenApiEventInstance } from './openapi.js';
92
92
  import { fetchDoc } from './docs.js';
93
- import { FlowSpec, FlowStep, getAgentFlow } from './agents/common.js';
93
+ import { FlowSpec, FlowStep, getAgentFlow } from './agents/flows.js';
94
94
 
95
95
  export type Result = any;
96
96
 
@@ -136,7 +136,12 @@ export class Environment extends Instance {
136
136
  private inDeleteMode: boolean = false;
137
137
  private inKernelMode: boolean = false;
138
138
  private suspensionId: string | undefined;
139
+ private preGeneratedSuspensionId: string;
139
140
  private activeCatchHandlers: Array<CatchHandlers>;
141
+ private eventExecutor: Function | undefined = undefined;
142
+ private statementsExecutor: Function | undefined = undefined;
143
+
144
+ private activeUserData: any = undefined;
140
145
 
141
146
  constructor(name?: string, parent?: Environment) {
142
147
  super(
@@ -158,6 +163,7 @@ export class Environment extends Instance {
158
163
  this.inKernelMode = parent.inKernelMode;
159
164
  this.activeCatchHandlers = parent.activeCatchHandlers;
160
165
  this.suspensionId = parent.suspensionId;
166
+ this.eventExecutor = parent.eventExecutor;
161
167
  } else {
162
168
  this.activeModule = DefaultModuleName;
163
169
  this.activeResolvers = new Map<string, Resolver>();
@@ -165,6 +171,7 @@ export class Environment extends Instance {
165
171
  this.activeCatchHandlers = new Array<CatchHandlers>();
166
172
  this.attributes.set('process', process);
167
173
  }
174
+ this.preGeneratedSuspensionId = crypto.randomUUID();
168
175
  }
169
176
 
170
177
  static from(
@@ -177,6 +184,7 @@ export class Environment extends Instance {
177
184
  env.activeResolvers = new Map<string, Resolver>();
178
185
  env.activeTransactions = new Map<string, string>();
179
186
  env.activeCatchHandlers = new Array<CatchHandlers>();
187
+ env.preGeneratedSuspensionId = parent.preGeneratedSuspensionId;
180
188
  }
181
189
  return env;
182
190
  }
@@ -306,7 +314,7 @@ export class Environment extends Instance {
306
314
 
307
315
  suspend(): string {
308
316
  if (this.suspensionId == undefined) {
309
- const id = crypto.randomUUID();
317
+ const id = this.preGeneratedSuspensionId;
310
318
  this.propagateSuspension(id);
311
319
  return id;
312
320
  } else {
@@ -314,6 +322,16 @@ export class Environment extends Instance {
314
322
  }
315
323
  }
316
324
 
325
+ releaseSuspension(): Environment {
326
+ this.suspensionId = undefined;
327
+ this.preGeneratedSuspensionId = crypto.randomUUID();
328
+ return this;
329
+ }
330
+
331
+ fetchSuspensionId(): string {
332
+ return this.preGeneratedSuspensionId;
333
+ }
334
+
317
335
  markForReturn(): Environment {
318
336
  if (this.parent) {
319
337
  this.parent.markForReturn();
@@ -326,6 +344,14 @@ export class Environment extends Instance {
326
344
  return this.returnFlag;
327
345
  }
328
346
 
347
+ propagateLastResult(): Environment {
348
+ if (this.parent) {
349
+ this.parent.lastResult = this.lastResult;
350
+ this.parent.propagateLastResult();
351
+ }
352
+ return this;
353
+ }
354
+
329
355
  resetReturnFlag(): Environment {
330
356
  if (this.returnFlag) {
331
357
  this.returnFlag = false;
@@ -570,11 +596,53 @@ export class Environment extends Instance {
570
596
  }
571
597
  return r;
572
598
  }
599
+
600
+ setEventExecutor(exec: Function): Environment {
601
+ this.eventExecutor = exec;
602
+ return this;
603
+ }
604
+
605
+ getEventExecutor(): Function | undefined {
606
+ return this.eventExecutor;
607
+ }
608
+
609
+ unsetEventExecutor(): Environment {
610
+ this.eventExecutor = undefined;
611
+ return this;
612
+ }
613
+
614
+ setStatementsExecutor(f: Function): Environment {
615
+ this.statementsExecutor = f;
616
+ return this;
617
+ }
618
+
619
+ getStatementsExecutor(): Function | undefined {
620
+ return this.statementsExecutor;
621
+ }
622
+
623
+ async callWithStatementsExecutor(exec: Function, f: Function): Promise<any> {
624
+ const oldExec = this.statementsExecutor;
625
+ this.statementsExecutor = exec;
626
+ try {
627
+ return await f();
628
+ } finally {
629
+ this.statementsExecutor = oldExec;
630
+ }
631
+ }
632
+
633
+ setActiveUserData(data: any): Environment {
634
+ this.activeUserData = data;
635
+ return this;
636
+ }
637
+
638
+ getActiveUserData(): any {
639
+ return this.activeUserData;
640
+ }
573
641
  }
574
642
 
575
643
  export const GlobalEnvironment = new Environment();
576
644
 
577
- export async function evaluate(
645
+ export let evaluate = async function (
578
646
  eventInstance: Instance,
579
647
  continuation?: Function,
580
648
  activeEnv?: Environment,
@@ -626,6 +694,12 @@ export async function evaluate(
626
694
  await env.commitAllTransactions();
627
695
  }
628
696
  }
697
+ };
698
+
699
+ export function setEvaluateFn(f: any): Function {
700
+ const oldf = evaluate;
701
+ evaluate = f;
702
+ return oldf;
629
703
  }
630
704
 
631
705
  export async function evaluateAsEvent(
@@ -661,27 +735,6 @@ export function makeEventEvaluator(moduleName: string): Function {
661
735
  };
662
736
  }
663
737
 
664
- function statemtentString(stmt: Statement): string {
665
- if (stmt.$cstNode) {
666
- return stmt.$cstNode.text;
667
- } else {
668
- throw new Error(`Failed to fetch text for statement - ${stmt}`);
669
- }
670
- }
671
-
672
- async function saveSuspension(cont: Statement[], env: Environment) {
673
- if (cont.length > 0) {
674
- const suspId = await createSuspension(
675
- env.getSuspensionId(),
676
- cont.map((stmt: Statement) => {
677
- return statemtentString(stmt);
678
- }),
679
- env
680
- );
681
- env.setLastResult({ suspension: suspId || 'null' });
682
- }
683
- }
684
-
685
738
  export async function evaluateStatements(
686
739
  stmts: Statement[],
687
740
  env: Environment,
@@ -710,7 +763,17 @@ async function evaluateAsyncPattern(
710
763
  await evaluatePattern(pat, env);
711
764
  maybeBindStatementResultToAlias(hints, env);
712
765
  if (env.isSuspended()) {
713
- await saveSuspension(thenStmts, env);
766
+ await createSuspension(
767
+ env.fetchSuspensionId(),
768
+ thenStmts.map((s: Statement) => {
769
+ if (s.$cstNode) {
770
+ return s.$cstNode.text;
771
+ } else {
772
+ throw new Error('failed to extract code for suspension statement');
773
+ }
774
+ }),
775
+ env
776
+ );
714
777
  } else {
715
778
  await evaluateStatements(thenStmts, env);
716
779
  }
@@ -722,7 +785,7 @@ async function evaluateAsyncPattern(
722
785
  }
723
786
  }
724
787
 
725
- async function evaluateStatement(stmt: Statement, env: Environment): Promise<void> {
788
+ export async function evaluateStatement(stmt: Statement, env: Environment): Promise<void> {
726
789
  const hints = stmt.hints;
727
790
  const hasHints = hints && hints.length > 0;
728
791
  const thenStmts: Statement[] | undefined = hasHints ? maybeFindThenStatements(hints) : undefined;
@@ -735,9 +798,13 @@ async function evaluateStatement(stmt: Statement, env: Environment): Promise<voi
735
798
  hints,
736
799
  Environment.from(env, env.name + 'async', true)
737
800
  );
801
+ env.setLastResult(env.fetchSuspensionId());
738
802
  if (isReturn(stmt.pattern)) {
739
803
  env.markForReturn();
740
804
  }
805
+ if (hasHints) {
806
+ maybeBindStatementResultToAlias(hints, env);
807
+ }
741
808
  return;
742
809
  }
743
810
  let handlersPushed = false;
@@ -768,7 +835,9 @@ async function maybeHandleNotFound(handlers: CatchHandlers | undefined, env: Env
768
835
  ) {
769
836
  const onNotFound = handlers ? handlers.get('not_found') : undefined;
770
837
  if (onNotFound) {
771
- await evaluateStatement(onNotFound, env);
838
+ const newEnv = new Environment('not-found-env', env).unsetEventExecutor();
839
+ await evaluateStatement(onNotFound, newEnv);
840
+ env.setLastResult(newEnv.getLastResult());
772
841
  }
773
842
  }
774
843
  }
@@ -780,13 +849,15 @@ async function maybeHandleError(
780
849
  ) {
781
850
  const handler = handlers ? handlers.get('error') : undefined;
782
851
  if (handler) {
783
- await evaluateStatement(handler, env);
852
+ const newEnv = new Environment('handler-env', env).unsetEventExecutor();
853
+ await evaluateStatement(handler, newEnv);
854
+ env.setLastResult(newEnv.getLastResult());
784
855
  } else {
785
856
  throw reason;
786
857
  }
787
858
  }
788
859
 
789
- function maybeBindStatementResultToAlias(hints: RuntimeHint[], env: Environment) {
860
+ export function maybeBindStatementResultToAlias(hints: RuntimeHint[], env: Environment) {
790
861
  for (let i = 0; i < hints.length; ++i) {
791
862
  const rh = hints[i];
792
863
  if (rh.aliasSpec) {
@@ -842,7 +913,7 @@ function maybeFindThenStatements(hints: RuntimeHint[]): Statement[] | undefined
842
913
  return undefined;
843
914
  }
844
915
 
845
- export async function parseAndEvaluateStatement(
916
+ export let parseAndEvaluateStatement = async function (
846
917
  stmtString: string,
847
918
  activeUserId?: string,
848
919
  actievEnv?: Environment
@@ -872,25 +943,71 @@ export async function parseAndEvaluateStatement(
872
943
  }
873
944
  }
874
945
  }
946
+ };
947
+
948
+ export function setParseAndEvaluateStatementFn(f: any): Function {
949
+ const oldf = parseAndEvaluateStatement;
950
+ parseAndEvaluateStatement = f;
951
+ return oldf;
875
952
  }
876
953
 
877
- async function evaluatePattern(pat: Pattern, env: Environment): Promise<void> {
954
+ export class PatternHandler {
955
+ async handleExpression(expr: Expr, env: Environment) {
956
+ await evaluateExpression(expr, env);
957
+ }
958
+
959
+ async handleCrudMap(crudMap: CrudMap, env: Environment) {
960
+ await evaluateCrudMap(crudMap, env);
961
+ }
962
+
963
+ async handleForEach(forEach: ForEach, env: Environment) {
964
+ await evaluateForEach(forEach, env);
965
+ }
966
+
967
+ async handleIf(_if: If, env: Environment) {
968
+ await evaluateIf(_if, env);
969
+ }
970
+
971
+ async handleDelete(del: Delete, env: Environment) {
972
+ await evaluateDelete(del, env);
973
+ }
974
+
975
+ async handlePurge(purge: Purge, env: Environment) {
976
+ await evaluatePurge(purge, env);
977
+ }
978
+
979
+ async handleFullTextSearch(fullTextSearch: FullTextSearch, env: Environment) {
980
+ await evaluateFullTextSearch(fullTextSearch, env);
981
+ }
982
+
983
+ async handleReturn(ret: Return, env: Environment) {
984
+ await evaluatePattern(ret.pattern, env);
985
+ }
986
+ }
987
+
988
+ const DefaultPatternHandler = new PatternHandler();
989
+
990
+ export async function evaluatePattern(
991
+ pat: Pattern,
992
+ env: Environment,
993
+ handler: PatternHandler = DefaultPatternHandler
994
+ ): Promise<void> {
878
995
  if (pat.expr) {
879
- await evaluateExpression(pat.expr, env);
996
+ await handler.handleExpression(pat.expr, env);
880
997
  } else if (pat.crudMap) {
881
- await evaluateCrudMap(pat.crudMap, env);
998
+ await handler.handleCrudMap(pat.crudMap, env);
882
999
  } else if (pat.forEach) {
883
- await evaluateForEach(pat.forEach, env);
1000
+ await handler.handleForEach(pat.forEach, env);
884
1001
  } else if (pat.if) {
885
- await evaluateIf(pat.if, env);
1002
+ await handler.handleIf(pat.if, env);
886
1003
  } else if (pat.delete) {
887
- await evaluateDelete(pat.delete, env);
1004
+ await handler.handleDelete(pat.delete, env);
888
1005
  } else if (pat.purge) {
889
- await evaluatePurge(pat.purge, env);
1006
+ await handler.handlePurge(pat.purge, env);
890
1007
  } else if (pat.fullTextSearch) {
891
- await evaluateFullTextSearch(pat.fullTextSearch, env);
1008
+ await handler.handleFullTextSearch(pat.fullTextSearch, env);
892
1009
  } else if (pat.return) {
893
- await evaluatePattern(pat.return.pat, env);
1010
+ await handler.handleReturn(pat.return, env);
894
1011
  env.markForReturn();
895
1012
  }
896
1013
  }
@@ -1247,7 +1364,12 @@ async function evaluateCrudMap(crud: CrudMap, env: Environment): Promise<void> {
1247
1364
  else if (isOpenApiEventInstance(inst)) await handleOpenApiEvent(inst, env);
1248
1365
  else if (isDocEventInstance(inst)) await handleDocEvent(inst, env);
1249
1366
  else {
1250
- await evaluate(inst, (result: Result) => env.setLastResult(result), env);
1367
+ const eventExec = env.getEventExecutor();
1368
+ if (eventExec) {
1369
+ await eventExec(inst, env);
1370
+ } else {
1371
+ await evaluate(inst, (result: Result) => env.setLastResult(result), env);
1372
+ }
1251
1373
  env.resetReturnFlag();
1252
1374
  }
1253
1375
  } else {
@@ -1256,7 +1378,7 @@ async function evaluateCrudMap(crud: CrudMap, env: Environment): Promise<void> {
1256
1378
  }
1257
1379
 
1258
1380
  const CoreAIModuleName = makeCoreModuleName('ai');
1259
- const DocEventName = `${CoreAIModuleName}/doc`;
1381
+ export const DocEventName = `${CoreAIModuleName}/doc`;
1260
1382
 
1261
1383
  function isDocEventInstance(inst: Instance): boolean {
1262
1384
  return isInstanceOfType(inst, DocEventName);
@@ -1406,6 +1528,7 @@ async function agentInvoke(agent: AgentInstance, msg: string, env: Environment):
1406
1528
  let result: string | undefined = env.getLastResult();
1407
1529
  logger.debug(`Agent ${agent.name} result: ${result}`);
1408
1530
  const isPlanner = agent.isPlanner();
1531
+ const stmtsExec = env.getStatementsExecutor();
1409
1532
  if (result) {
1410
1533
  if (isPlanner) {
1411
1534
  let retries = 0;
@@ -1428,9 +1551,18 @@ async function agentInvoke(agent: AgentInstance, msg: string, env: Environment):
1428
1551
  }
1429
1552
  if (isWf) {
1430
1553
  const wf = await parseWorkflow(rs);
1431
- await evaluateStatements(wf.statements, env);
1554
+ if (stmtsExec) {
1555
+ await stmtsExec(wf.statements, env);
1556
+ } else {
1557
+ await evaluateStatements(wf.statements, env);
1558
+ }
1432
1559
  } else {
1433
- env.setLastResult(await parseAndEvaluateStatement(rs, undefined, env));
1560
+ if (stmtsExec) {
1561
+ const stmt = await parseStatement(rs);
1562
+ env.setLastResult(await stmtsExec([stmt], env));
1563
+ } else {
1564
+ env.setLastResult(await parseAndEvaluateStatement(rs, undefined, env));
1565
+ }
1434
1566
  }
1435
1567
  break;
1436
1568
  } catch (err: any) {
@@ -1448,19 +1580,19 @@ async function agentInvoke(agent: AgentInstance, msg: string, env: Environment):
1448
1580
  }
1449
1581
  }
1450
1582
  }
1451
- if (agent.output) {
1452
- await pushToAgent(agent.output, env.getLastResult(), env);
1453
- }
1454
1583
  } else {
1455
1584
  throw new Error(`Agent ${agent.name} failed to generate a response`);
1456
1585
  }
1457
1586
  }
1458
1587
 
1459
- async function handleAgentInvocation(agentEventInst: Instance, env: Environment): Promise<void> {
1588
+ export async function handleAgentInvocation(
1589
+ agentEventInst: Instance,
1590
+ env: Environment
1591
+ ): Promise<void> {
1460
1592
  const agent: AgentInstance = await findAgentByName(agentEventInst.name, env);
1461
1593
  const origMsg: any = agentEventInst.lookup('message');
1462
1594
  const msg: string = isString(origMsg) ? origMsg : agentInputAsString(origMsg);
1463
- const flow = getAgentFlow(agent.name);
1595
+ const flow = getAgentFlow(agent.name, agent.moduleName);
1464
1596
  if (flow) {
1465
1597
  await handleAgentInvocationWithFlow(agent, flow, msg, env);
1466
1598
  } else {
@@ -1476,6 +1608,7 @@ async function handleAgentInvocationWithFlow(
1476
1608
  msg: string,
1477
1609
  env: Environment
1478
1610
  ): Promise<void> {
1611
+ rootAgent.markAsFlowExecutor();
1479
1612
  await iterateOnFlow(flow, rootAgent, msg, env);
1480
1613
  }
1481
1614
 
@@ -1499,9 +1632,9 @@ export async function restartFlow(
1499
1632
  env: Environment
1500
1633
  ): Promise<void> {
1501
1634
  const [_, agentName, step, ctx] = flowContext;
1502
- const flow = getAgentFlow(agentName);
1635
+ const rootAgent: AgentInstance = await findAgentByName(agentName, env);
1636
+ const flow = getAgentFlow(agentName, rootAgent.moduleName);
1503
1637
  if (flow) {
1504
- const rootAgent = await findAgentByName(agentName, env);
1505
1638
  const newCtx = `${ctx}\n${step} --> ${userData}\n`;
1506
1639
  await iterateOnFlow(flow, rootAgent, newCtx, env);
1507
1640
  }
@@ -1541,6 +1674,7 @@ async function iterateOnFlow(
1541
1674
  if (env.isSuspended()) {
1542
1675
  console.debug(`${iterId} suspending iteration on step ${step}`);
1543
1676
  await saveFlowSuspension(rootAgent, context, step, env);
1677
+ env.releaseSuspension();
1544
1678
  return;
1545
1679
  }
1546
1680
  const r = env.getLastResult();
@@ -1570,13 +1704,7 @@ function agentInputAsString(result: any): string {
1570
1704
  return result;
1571
1705
  }
1572
1706
 
1573
- async function pushToAgent(agentName: string, result: any, env: Environment) {
1574
- const r = escapeSpecialChars(agentInputAsString(result));
1575
- const pat = `{${agentName} {message "\n${r}"}}`;
1576
- env.setLastResult(await parseAndEvaluateStatement(pat, undefined, env));
1577
- }
1578
-
1579
- async function handleOpenApiEvent(eventInst: Instance, env: Environment): Promise<void> {
1707
+ export async function handleOpenApiEvent(eventInst: Instance, env: Environment): Promise<void> {
1580
1708
  const r = await invokeOpenApiEvent(
1581
1709
  eventInst.moduleName,
1582
1710
  eventInst.name,
@@ -1628,11 +1756,19 @@ async function evaluateDeleteHelper(
1628
1756
  ): Promise<void> {
1629
1757
  const newEnv = Environment.from(env).setInDeleteMode(true);
1630
1758
  await evaluatePattern(pattern, newEnv);
1631
- const inst: Instance[] | Instance = newEnv.getLastResult();
1759
+ await maybeDeleteQueriedInstances(newEnv, env, purge);
1760
+ }
1761
+
1762
+ export async function maybeDeleteQueriedInstances(
1763
+ queryEnv: Environment,
1764
+ env: Environment,
1765
+ purge: boolean = false
1766
+ ): Promise<void> {
1767
+ const inst: Instance[] | Instance = queryEnv.getLastResult();
1632
1768
  let resolver: Resolver = Resolver.Default;
1633
1769
  if (inst instanceof Array) {
1634
1770
  if (inst.length > 0) {
1635
- resolver = await getResolverForPath(inst[0].name, inst[0].moduleName, newEnv);
1771
+ resolver = await getResolverForPath(inst[0].name, inst[0].moduleName, queryEnv);
1636
1772
  const finalResult: Array<any> = new Array<any>();
1637
1773
  for (let i = 0; i < inst.length; ++i) {
1638
1774
  await runPreDeleteEvents(inst[i], env);
@@ -1640,18 +1776,18 @@ async function evaluateDeleteHelper(
1640
1776
  await runPostDeleteEvents(inst[i], env);
1641
1777
  finalResult.push(r);
1642
1778
  }
1643
- newEnv.setLastResult(finalResult);
1779
+ queryEnv.setLastResult(finalResult);
1644
1780
  } else {
1645
- newEnv.setLastResult(inst);
1781
+ queryEnv.setLastResult(inst);
1646
1782
  }
1647
1783
  } else {
1648
- resolver = await getResolverForPath(inst.name, inst.moduleName, newEnv);
1784
+ resolver = await getResolverForPath(inst.name, inst.moduleName, queryEnv);
1649
1785
  await runPreDeleteEvents(inst, env);
1650
1786
  const r: Instance | null = await resolver.deleteInstance(inst, purge);
1651
1787
  await runPostDeleteEvents(inst, env);
1652
- newEnv.setLastResult(r);
1788
+ queryEnv.setLastResult(r);
1653
1789
  }
1654
- env.setLastResult(newEnv.getLastResult());
1790
+ env.setLastResult(queryEnv.getLastResult());
1655
1791
  }
1656
1792
 
1657
1793
  async function evaluateDelete(delStmt: Delete, env: Environment): Promise<void> {
@@ -1662,7 +1798,7 @@ async function evaluatePurge(purgeStmt: Purge, env: Environment): Promise<void>
1662
1798
  await evaluateDeleteHelper(purgeStmt.pattern, true, env);
1663
1799
  }
1664
1800
 
1665
- async function evaluateExpression(expr: Expr, env: Environment): Promise<void> {
1801
+ export async function evaluateExpression(expr: Expr, env: Environment): Promise<void> {
1666
1802
  let result: Result = EmptyResult;
1667
1803
  if (isBinExpr(expr)) {
1668
1804
  await evaluateExpression(expr.e1, env);
@@ -29,6 +29,7 @@ import {
29
29
  Expr,
30
30
  FlowDefinition,
31
31
  isFlowDefinition,
32
+ Literal,
32
33
  } from '../language/generated/ast.js';
33
34
  import {
34
35
  addEntity,
@@ -68,7 +69,17 @@ import { maybeGetValidationErrors, parse, parseModule, parseWorkflow } from '../
68
69
  import { logger } from './logger.js';
69
70
  import { Environment, evaluateStatements, GlobalEnvironment } from './interpreter.js';
70
71
  import { createPermission, createRole } from './modules/auth.js';
71
- import { AgentEntityName, CoreAIModuleName, LlmEntityName } from './modules/ai.js';
72
+ import {
73
+ AgentCondition,
74
+ AgentEntityName,
75
+ AgentGlossaryEntry,
76
+ AgentScenario,
77
+ CoreAIModuleName,
78
+ LlmEntityName,
79
+ registerAgentDirectives,
80
+ registerAgentGlossary,
81
+ registerAgentScenarios,
82
+ } from './modules/ai.js';
72
83
  import { getDefaultLLMService } from './agents/registry.js';
73
84
  import { GenericResolver, GenericResolverMethods } from './resolvers/interface.js';
74
85
  import { registerResolver, setResolver } from './resolvers/registry.js';
@@ -77,7 +88,7 @@ import { getModuleFn, importModule } from './jsmodules.js';
77
88
  import { SetSubscription } from './defs.js';
78
89
  import { ExtendedFileSystem } from '../utils/fs/interfaces.js';
79
90
  import z from 'zod';
80
- import { registerAgentFlow, registerFlow } from './agents/common.js';
91
+ import { registerAgentFlow, registerFlow } from './agents/flows.js';
81
92
 
82
93
  export async function extractDocument(
83
94
  fileName: string,
@@ -462,6 +473,99 @@ export async function runStandaloneStatements() {
462
473
  }
463
474
  }
464
475
 
476
+ function processAgentDirectives(agentName: string, value: Literal): AgentCondition[] | undefined {
477
+ if (value.array) {
478
+ const conds = new Array<AgentCondition>();
479
+ value.array.vals.forEach((stmt: Statement) => {
480
+ const expr = stmt.pattern.expr;
481
+ if (expr && isLiteral(expr) && expr.map) {
482
+ let cond: string | undefined;
483
+ let then: string | undefined;
484
+ expr.map.entries.forEach((me: MapEntry) => {
485
+ const v = isLiteral(me.value) ? me.value.str : undefined;
486
+ if (v) {
487
+ if (me.key.str == 'if') {
488
+ cond = v;
489
+ } else if (me.key.str == 'then') {
490
+ then = v;
491
+ }
492
+ }
493
+ });
494
+ if (cond && then) {
495
+ conds?.push({ cond, then });
496
+ } else {
497
+ throw new Error(`Invalid condition spec in agent ${agentName}`);
498
+ }
499
+ }
500
+ });
501
+ return conds;
502
+ }
503
+ return undefined;
504
+ }
505
+
506
+ function processAgentScenarios(agentName: string, value: Literal): AgentScenario[] | undefined {
507
+ if (value.array) {
508
+ const scenarios = new Array<AgentScenario>();
509
+ value.array.vals.forEach((stmt: Statement) => {
510
+ const expr = stmt.pattern.expr;
511
+ if (expr && isLiteral(expr) && expr.map) {
512
+ let user: string | undefined;
513
+ let ai: string | undefined;
514
+ expr.map.entries.forEach((me: MapEntry) => {
515
+ const v = isLiteral(me.value) ? me.value.str : undefined;
516
+ if (v) {
517
+ if (me.key.str == 'user') {
518
+ user = v;
519
+ } else if (me.key.str == 'ai') {
520
+ ai = v;
521
+ }
522
+ }
523
+ });
524
+ if (user && ai) {
525
+ scenarios.push({ user, ai });
526
+ } else {
527
+ throw new Error(`Invalid glossary spec in agent ${agentName}`);
528
+ }
529
+ }
530
+ });
531
+ return scenarios;
532
+ }
533
+ return undefined;
534
+ }
535
+
536
+ function processAgentGlossary(agentName: string, value: Literal): AgentGlossaryEntry[] | undefined {
537
+ if (value.array) {
538
+ const gls = new Array<AgentGlossaryEntry>();
539
+ value.array.vals.forEach((stmt: Statement) => {
540
+ const expr = stmt.pattern.expr;
541
+ if (expr && isLiteral(expr) && expr.map) {
542
+ let name: string | undefined;
543
+ let meaning: string | undefined;
544
+ let synonyms: string | undefined;
545
+ expr.map.entries.forEach((me: MapEntry) => {
546
+ const v = isLiteral(me.value) ? me.value.str : undefined;
547
+ if (v) {
548
+ if (me.key.str == 'name') {
549
+ name = v;
550
+ } else if (me.key.str == 'meaning') {
551
+ meaning = v;
552
+ } else if (me.key.str == 'synonyms') {
553
+ synonyms = v;
554
+ }
555
+ }
556
+ });
557
+ if (name && meaning) {
558
+ gls.push({ name, meaning, synonyms });
559
+ } else {
560
+ throw new Error(`Invalid glossary spec in agent ${agentName}`);
561
+ }
562
+ }
563
+ });
564
+ return gls;
565
+ }
566
+ return undefined;
567
+ }
568
+
465
569
  async function addAgentDefinition(def: AgentDefinition, moduleName: string) {
466
570
  let llmName: string | undefined = undefined;
467
571
  const name = def.name;
@@ -470,6 +574,9 @@ async function addAgentDefinition(def: AgentDefinition, moduleName: string) {
470
574
  const attrs = newInstanceAttributes();
471
575
  attrsStrs.push(`moduleName "${moduleName}"`);
472
576
  attrs.set('moduleName', moduleName);
577
+ let conds: AgentCondition[] | undefined = undefined;
578
+ let scenarios: AgentScenario[] | undefined = undefined;
579
+ let glossary: AgentGlossaryEntry[] | undefined = undefined;
473
580
  def.body?.attributes.forEach((apdef: GenericPropertyDef) => {
474
581
  if (apdef.name == 'flows') {
475
582
  let fnames: string | undefined = undefined;
@@ -491,6 +598,12 @@ async function addAgentDefinition(def: AgentDefinition, moduleName: string) {
491
598
  } else {
492
599
  throw new Error(`Invalid flows list in agent ${name}`);
493
600
  }
601
+ } else if (apdef.name == 'directives') {
602
+ conds = processAgentDirectives(name, apdef.value);
603
+ } else if (apdef.name == 'scenarios') {
604
+ scenarios = processAgentScenarios(name, apdef.value);
605
+ } else if (apdef.name == 'glossary') {
606
+ glossary = processAgentGlossary(name, apdef.value);
494
607
  } else {
495
608
  let v: any = undefined;
496
609
  if (apdef.value.array) {
@@ -544,6 +657,15 @@ async function addAgentDefinition(def: AgentDefinition, moduleName: string) {
544
657
  (await parseWorkflow(`workflow A {${wf}}`)).statements.forEach((stmt: Statement) => {
545
658
  addStandaloneStatement(stmt, moduleName, false);
546
659
  });
660
+ if (conds) {
661
+ registerAgentDirectives(moduleName, name, conds);
662
+ }
663
+ if (scenarios) {
664
+ registerAgentScenarios(moduleName, name, scenarios);
665
+ }
666
+ if (glossary) {
667
+ registerAgentGlossary(moduleName, name, glossary);
668
+ }
547
669
  // Don't add llm to module attrs if it wasn't originally specified
548
670
  addAgent(def.name, attrs, moduleName);
549
671
  }