agentlang 0.0.3 → 0.0.4

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 +16 -47
  2. package/out/api/http.d.ts.map +1 -1
  3. package/out/api/http.js +12 -0
  4. package/out/api/http.js.map +1 -1
  5. package/out/cli/main.d.ts +1 -3
  6. package/out/cli/main.d.ts.map +1 -1
  7. package/out/cli/main.js +6 -12
  8. package/out/cli/main.js.map +1 -1
  9. package/out/language/generated/ast.d.ts +80 -18
  10. package/out/language/generated/ast.d.ts.map +1 -1
  11. package/out/language/generated/ast.js +119 -26
  12. package/out/language/generated/ast.js.map +1 -1
  13. package/out/language/generated/grammar.d.ts +1 -1
  14. package/out/language/generated/grammar.d.ts.map +1 -1
  15. package/out/language/generated/grammar.js +831 -238
  16. package/out/language/generated/grammar.js.map +1 -1
  17. package/out/language/generated/module.d.ts +1 -1
  18. package/out/language/generated/module.js +1 -1
  19. package/out/language/main.cjs +995 -331
  20. package/out/language/main.cjs.map +2 -2
  21. package/out/language/parser.js +13 -6
  22. package/out/language/parser.js.map +1 -1
  23. package/out/runtime/agents/common.d.ts +1 -1
  24. package/out/runtime/agents/common.d.ts.map +1 -1
  25. package/out/runtime/agents/common.js +1 -1
  26. package/out/runtime/auth/cognito.d.ts +4 -1
  27. package/out/runtime/auth/cognito.d.ts.map +1 -1
  28. package/out/runtime/auth/cognito.js +540 -73
  29. package/out/runtime/auth/cognito.js.map +1 -1
  30. package/out/runtime/auth/defs.d.ts +3 -0
  31. package/out/runtime/auth/defs.d.ts.map +1 -1
  32. package/out/runtime/auth/defs.js +17 -1
  33. package/out/runtime/auth/defs.js.map +1 -1
  34. package/out/runtime/auth/interface.d.ts +6 -1
  35. package/out/runtime/auth/interface.d.ts.map +1 -1
  36. package/out/runtime/defs.d.ts +21 -0
  37. package/out/runtime/defs.d.ts.map +1 -1
  38. package/out/runtime/defs.js +35 -0
  39. package/out/runtime/defs.js.map +1 -1
  40. package/out/runtime/interpreter.d.ts.map +1 -1
  41. package/out/runtime/interpreter.js +45 -36
  42. package/out/runtime/interpreter.js.map +1 -1
  43. package/out/runtime/loader.d.ts +4 -2
  44. package/out/runtime/loader.d.ts.map +1 -1
  45. package/out/runtime/loader.js +148 -29
  46. package/out/runtime/loader.js.map +1 -1
  47. package/out/runtime/module.d.ts +48 -5
  48. package/out/runtime/module.d.ts.map +1 -1
  49. package/out/runtime/module.js +200 -9
  50. package/out/runtime/module.js.map +1 -1
  51. package/out/runtime/modules/ai.d.ts +7 -5
  52. package/out/runtime/modules/ai.d.ts.map +1 -1
  53. package/out/runtime/modules/ai.js +50 -24
  54. package/out/runtime/modules/ai.js.map +1 -1
  55. package/out/runtime/modules/auth.d.ts +17 -1
  56. package/out/runtime/modules/auth.d.ts.map +1 -1
  57. package/out/runtime/modules/auth.js +282 -30
  58. package/out/runtime/modules/auth.js.map +1 -1
  59. package/out/runtime/modules/core.d.ts.map +1 -1
  60. package/out/runtime/modules/core.js +3 -1
  61. package/out/runtime/modules/core.js.map +1 -1
  62. package/out/runtime/relgraph.d.ts.map +1 -1
  63. package/out/runtime/relgraph.js +2 -2
  64. package/out/runtime/relgraph.js.map +1 -1
  65. package/out/runtime/resolvers/interface.d.ts +37 -2
  66. package/out/runtime/resolvers/interface.d.ts.map +1 -1
  67. package/out/runtime/resolvers/interface.js +103 -5
  68. package/out/runtime/resolvers/interface.js.map +1 -1
  69. package/out/runtime/resolvers/registry.d.ts +3 -2
  70. package/out/runtime/resolvers/registry.d.ts.map +1 -1
  71. package/out/runtime/resolvers/registry.js +3 -0
  72. package/out/runtime/resolvers/registry.js.map +1 -1
  73. package/out/runtime/state.d.ts +31 -3
  74. package/out/runtime/state.d.ts.map +1 -1
  75. package/out/runtime/state.js +11 -1
  76. package/out/runtime/state.js.map +1 -1
  77. package/out/runtime/util.d.ts +4 -0
  78. package/out/runtime/util.d.ts.map +1 -1
  79. package/out/runtime/util.js +16 -0
  80. package/out/runtime/util.js.map +1 -1
  81. package/out/syntaxes/agentlang.monarch.js +2 -2
  82. package/out/syntaxes/agentlang.monarch.js.map +1 -1
  83. package/out/utils/http.d.ts +2 -0
  84. package/out/utils/http.d.ts.map +1 -0
  85. package/out/utils/http.js +5 -0
  86. package/out/utils/http.js.map +1 -0
  87. package/package.json +8 -6
  88. package/src/api/http.ts +15 -0
  89. package/src/cli/main.ts +6 -12
  90. package/src/language/agentlang.langium +31 -10
  91. package/src/language/generated/ast.ts +212 -44
  92. package/src/language/generated/grammar.ts +831 -238
  93. package/src/language/generated/module.ts +1 -1
  94. package/src/language/parser.ts +12 -8
  95. package/src/runtime/agents/common.ts +1 -1
  96. package/src/runtime/auth/cognito.ts +605 -74
  97. package/src/runtime/auth/defs.ts +17 -1
  98. package/src/runtime/auth/interface.ts +6 -1
  99. package/src/runtime/defs.ts +45 -0
  100. package/src/runtime/interpreter.ts +43 -34
  101. package/src/runtime/loader.ts +159 -30
  102. package/src/runtime/module.ts +243 -10
  103. package/src/runtime/modules/ai.ts +52 -28
  104. package/src/runtime/modules/auth.ts +330 -38
  105. package/src/runtime/modules/core.ts +3 -1
  106. package/src/runtime/relgraph.ts +2 -8
  107. package/src/runtime/resolvers/interface.ts +141 -6
  108. package/src/runtime/resolvers/registry.ts +5 -2
  109. package/src/runtime/state.ts +11 -1
  110. package/src/runtime/util.ts +17 -0
  111. package/src/syntaxes/agentlang.monarch.ts +2 -2
  112. package/src/utils/http.ts +5 -0
  113. package/src/index.ts +0 -29
@@ -4,13 +4,29 @@ import { AppConfig } from '../state.js';
4
4
  export const AdminUserId = '00000000-0000-0000-0000-000000000000';
5
5
 
6
6
  export function isAuthEnabled(): boolean {
7
- if (AppConfig && AppConfig.rbacEnabled == true) {
7
+ if (AppConfig?.auth?.enabled == true) {
8
8
  return true;
9
9
  } else {
10
10
  return false;
11
11
  }
12
12
  }
13
13
 
14
+ export let InternalRbacEnabled = false;
15
+
16
+ export function isRbacEnabled(): boolean {
17
+ return InternalRbacEnabled || (isAuthEnabled() && AppConfig?.rbac?.enabled == true);
18
+ }
19
+
20
+ export async function callWithRbac(f: Function): Promise<void> {
21
+ const old = InternalRbacEnabled;
22
+ InternalRbacEnabled = true;
23
+ try {
24
+ await f();
25
+ } finally {
26
+ InternalRbacEnabled = old;
27
+ }
28
+ }
29
+
14
30
  export type ActiveSessionInfo = {
15
31
  sessionId: string;
16
32
  userId: string;
@@ -10,6 +10,9 @@ export type SessionInfo = {
10
10
  sessionId: string; // a UUID
11
11
  userId: string; // UUID
12
12
  authToken: string;
13
+ idToken?: string;
14
+ accessToken?: string;
15
+ refreshToken?: string;
13
16
  systemSesionInfo?: any;
14
17
  };
15
18
 
@@ -27,5 +30,7 @@ export interface AgentlangAuth {
27
30
  ): any;
28
31
  login(username: string, password: string, env: Environment, cb: LoginCallback): any;
29
32
  logout(sessionInfo: SessionInfo, env: Environment, cb?: LogoutCallback): any;
30
- verifyToken(token: string, env: Environment): any;
33
+ verifyToken(token: string, env?: Environment): any;
34
+ getUser(userId: string, env: Environment): Promise<UserInfo>;
35
+ getUserByEmail(email: string, env: Environment): Promise<UserInfo>;
31
36
  }
@@ -31,3 +31,48 @@ export class BadRequestError extends Error {
31
31
  super(message ? asUnauthMessage(message) : 'BadRequest', options);
32
32
  }
33
33
  }
34
+
35
+ export class UserNotFoundError extends Error {
36
+ constructor(message?: string, options?: ErrorOptions) {
37
+ super(message || 'User not found', options);
38
+ }
39
+ }
40
+
41
+ export class UserNotConfirmedError extends Error {
42
+ constructor(message?: string, options?: ErrorOptions) {
43
+ super(
44
+ message || 'User account is not confirmed. Please check your email for verification code.',
45
+ options
46
+ );
47
+ }
48
+ }
49
+
50
+ export class PasswordResetRequiredError extends Error {
51
+ constructor(message?: string, options?: ErrorOptions) {
52
+ super(message || 'Password reset is required for this account', options);
53
+ }
54
+ }
55
+
56
+ export class TooManyRequestsError extends Error {
57
+ constructor(message?: string, options?: ErrorOptions) {
58
+ super(message || 'Too many requests. Please try again later.', options);
59
+ }
60
+ }
61
+
62
+ export class InvalidParameterError extends Error {
63
+ constructor(message?: string, options?: ErrorOptions) {
64
+ super(message || 'Invalid parameters provided', options);
65
+ }
66
+ }
67
+
68
+ export class ExpiredCodeError extends Error {
69
+ constructor(message?: string, options?: ErrorOptions) {
70
+ super(message || 'The verification code has expired. Please request a new one.', options);
71
+ }
72
+ }
73
+
74
+ export class CodeMismatchError extends Error {
75
+ constructor(message?: string, options?: ErrorOptions) {
76
+ super(message || 'The verification code is incorrect. Please try again.', options);
77
+ }
78
+ }
@@ -24,7 +24,6 @@ import {
24
24
  SelectIntoSpec,
25
25
  SetAttribute,
26
26
  Statement,
27
- Upsert,
28
27
  } from '../language/generated/ast.js';
29
28
  import {
30
29
  defineAgentEvent,
@@ -33,7 +32,7 @@ import {
33
32
  getWorkflow,
34
33
  Instance,
35
34
  InstanceAttributes,
36
- isAgentEvent,
35
+ isAgentEventInstance,
37
36
  isBetweenRelationship,
38
37
  isContainsRelationship,
39
38
  isEmptyWorkflow,
@@ -62,13 +61,14 @@ import {
62
61
  makeFqName,
63
62
  Path,
64
63
  QuerySuffix,
64
+ restoreSpecialChars,
65
65
  splitFqName,
66
66
  splitRefs,
67
67
  } from './util.js';
68
68
  import { getResolver, getResolverNameForPath } from './resolvers/registry.js';
69
69
  import { parseStatement, parseWorkflow } from '../language/parser.js';
70
70
  import { ActiveSessionInfo, AdminSession, AdminUserId } from './auth/defs.js';
71
- import { Agent, AgentFqName, findAgentByName } from './modules/ai.js';
71
+ import { AgentInstance, AgentEntityName, AgentFqName, findAgentByName } from './modules/ai.js';
72
72
  import { logger } from './logger.js';
73
73
  import { ParentAttributeName, PathAttributeName, PathAttributeNameQuery } from './defs.js';
74
74
  import {
@@ -602,8 +602,6 @@ async function evaluatePattern(pat: Pattern, env: Environment): Promise<void> {
602
602
  await evaluateDelete(pat.delete, env);
603
603
  } else if (pat.purge) {
604
604
  await evaluatePurge(pat.purge, env);
605
- } else if (pat.upsert) {
606
- await evaluateUpsert(pat.upsert, env);
607
605
  } else if (pat.fullTextSearch) {
608
606
  await evaluateFullTextSearch(pat.fullTextSearch, env);
609
607
  }
@@ -644,7 +642,7 @@ async function evaluateLiteral(lit: Literal, env: Environment): Promise<void> {
644
642
  else if (lit.array != undefined) await realizeArray(lit.array, env);
645
643
  else if (lit.map != undefined) await realizeMap(lit.map, env);
646
644
  else if (lit.num != undefined) env.setLastResult(lit.num);
647
- else if (lit.str != undefined) env.setLastResult(lit.str);
645
+ else if (lit.str != undefined) env.setLastResult(restoreSpecialChars(lit.str));
648
646
  else if (lit.bool != undefined) env.setLastResult(lit.bool == 'true' ? true : false);
649
647
  }
650
648
 
@@ -694,7 +692,7 @@ async function lookupOneOfVals(fqName: string, env: Environment): Promise<Instan
694
692
 
695
693
  async function patternToInstance(
696
694
  entryName: string,
697
- attributes: SetAttribute[],
695
+ attributes: SetAttribute[] | undefined,
698
696
  env: Environment
699
697
  ): Promise<Instance> {
700
698
  const attrs: InstanceAttributes = newInstanceAttributes();
@@ -704,22 +702,24 @@ async function patternToInstance(
704
702
  if (isQueryAll) {
705
703
  entryName = entryName.slice(0, entryName.length - 1);
706
704
  }
707
- for (let i = 0; i < attributes.length; ++i) {
708
- const a: SetAttribute = attributes[i];
709
- await evaluateExpression(a.value, env);
710
- const v: Result = env.getLastResult();
711
- let aname: string = a.name;
712
- if (aname.endsWith(QuerySuffix)) {
713
- if (isQueryAll) {
714
- throw new Error(`Cannot specifiy query attribute ${aname} here`);
705
+ if (attributes) {
706
+ for (let i = 0; i < attributes.length; ++i) {
707
+ const a: SetAttribute = attributes[i];
708
+ await evaluateExpression(a.value, env);
709
+ const v: Result = env.getLastResult();
710
+ let aname: string = a.name;
711
+ if (aname.endsWith(QuerySuffix)) {
712
+ if (isQueryAll) {
713
+ throw new Error(`Cannot specifiy query attribute ${aname} here`);
714
+ }
715
+ if (qattrs == undefined) qattrs = newInstanceAttributes();
716
+ if (qattrVals == undefined) qattrVals = newInstanceAttributes();
717
+ aname = aname.slice(0, aname.length - 1);
718
+ qattrs.set(aname, a.op == undefined ? '=' : a.op);
719
+ qattrVals.set(aname, v);
720
+ } else {
721
+ attrs.set(aname, v);
715
722
  }
716
- if (qattrs == undefined) qattrs = newInstanceAttributes();
717
- if (qattrVals == undefined) qattrVals = newInstanceAttributes();
718
- aname = aname.slice(0, aname.length - 1);
719
- qattrs.set(aname, a.op == undefined ? '=' : a.op);
720
- qattrVals.set(aname, v);
721
- } else {
722
- attrs.set(aname, v);
723
723
  }
724
724
  }
725
725
  let moduleName = env.getActiveModuleName();
@@ -761,7 +761,10 @@ async function maybeValidateOneOfRefs(inst: Instance, env: Environment) {
761
761
  }
762
762
 
763
763
  async function evaluateCrudMap(crud: CrudMap, env: Environment): Promise<void> {
764
- const inst: Instance = await patternToInstance(crud.name, crud.attributes, env);
764
+ if (!env.isInUpsertMode() && crud.upsert) {
765
+ return await evaluateUpsert(crud, env);
766
+ }
767
+ const inst: Instance = await patternToInstance(crud.name, crud.body?.attributes, env);
765
768
  const entryName = inst.name;
766
769
  const moduleName = inst.moduleName;
767
770
  const attrs = inst.attributes;
@@ -802,7 +805,7 @@ async function evaluateCrudMap(crud: CrudMap, env: Environment): Promise<void> {
802
805
  r = await res.createInstance(inst);
803
806
  await runPostCreateEvents(inst, env);
804
807
  }
805
- if (r && entryName == 'agent') {
808
+ if (r && entryName == AgentEntityName) {
806
809
  defineAgentEvent(env.getActiveModuleName(), r.lookup('name'));
807
810
  }
808
811
  env.setLastResult(r);
@@ -922,7 +925,7 @@ async function evaluateCrudMap(crud: CrudMap, env: Environment): Promise<void> {
922
925
  }
923
926
  }
924
927
  } else if (isEventInstance(inst)) {
925
- if (isAgentEvent(inst)) await handleAgentInvocation(inst, env);
928
+ if (isAgentEventInstance(inst)) await handleAgentInvocation(inst, env);
926
929
  else await evaluate(inst, (result: Result) => env.setLastResult(result), env);
927
930
  } else {
928
931
  env.setLastResult(inst);
@@ -1029,7 +1032,7 @@ async function walkJoinQueryPattern(
1029
1032
  await walkJoinQueryPattern(crudMap.relationships[i], subJoins, env);
1030
1033
  }
1031
1034
  }
1032
- const qInst = await patternToInstance(crudMap.name, crudMap.attributes, env);
1035
+ const qInst = await patternToInstance(crudMap.name, crudMap.body?.attributes, env);
1033
1036
  joinsSpec.push({
1034
1037
  relationship: getRelationship(rp.name, qInst.moduleName),
1035
1038
  queryInstance: qInst,
@@ -1042,24 +1045,30 @@ async function walkJoinQueryPattern(
1042
1045
  }
1043
1046
 
1044
1047
  async function handleAgentInvocation(agentEventInst: Instance, env: Environment): Promise<void> {
1045
- const agent: Agent = await findAgentByName(agentEventInst.name, env);
1048
+ const agent: AgentInstance = await findAgentByName(agentEventInst.name, env);
1046
1049
  await agent.invoke(agentEventInst.lookup('message'), env);
1047
1050
  const result: string = env.getLastResult();
1048
1051
  if (agent.isPlanner()) {
1049
1052
  logger.debug(`Agent ${agent.name} generated pattern: ${result}`);
1050
- if (result.trimStart().startsWith('workflow')) {
1051
- await parseWorkflow(result); // check for errors
1052
- return;
1053
- } else {
1054
- env.setLastResult(await parseAndEvaluateStatement(result, undefined, env));
1053
+ try {
1054
+ if (result.trimStart().startsWith('workflow')) {
1055
+ await parseWorkflow(result);
1056
+ return;
1057
+ } else {
1058
+ env.setLastResult(await parseAndEvaluateStatement(result, undefined, env));
1059
+ }
1060
+ } catch (err: any) {
1061
+ logger.error(
1062
+ `Failed to evaluate pattern generated by agent ${agent.name} - ${result}, ${err}`
1063
+ );
1055
1064
  }
1056
1065
  }
1057
1066
  }
1058
1067
 
1059
- async function evaluateUpsert(upsert: Upsert, env: Environment): Promise<void> {
1068
+ async function evaluateUpsert(crud: CrudMap, env: Environment): Promise<void> {
1060
1069
  env.setInUpsertMode(true);
1061
1070
  try {
1062
- await evaluateCrudMap(upsert.pattern, env);
1071
+ await evaluateCrudMap(crud, env);
1063
1072
  } finally {
1064
1073
  env.setInUpsertMode(false);
1065
1074
  }
@@ -3,8 +3,6 @@ import { createAgentlangServices } from '../language/agentlang-module.js';
3
3
  import {
4
4
  Import,
5
5
  RbacSpecEntries,
6
- RbacSpecEntry,
7
- RbacOpr,
8
6
  ModuleDefinition,
9
7
  Definition,
10
8
  isEntityDefinition,
@@ -19,6 +17,13 @@ import {
19
17
  Statement,
20
18
  isStandaloneStatement,
21
19
  SchemaDefinition,
20
+ isAgentDefinition,
21
+ AgentDefinition,
22
+ SetAttribute,
23
+ isLiteral,
24
+ isResolverDefinition,
25
+ ResolverDefinition,
26
+ ResolverMethodSpec,
22
27
  } from '../language/generated/ast.js';
23
28
  import {
24
29
  addEntity,
@@ -36,10 +41,14 @@ import {
36
41
  isModule,
37
42
  getUserModuleNames,
38
43
  removeModule,
44
+ newInstanceAttributes,
45
+ addAgent,
39
46
  } from './module.js';
40
47
  import {
41
48
  findRbacSchema,
49
+ getModuleFn,
42
50
  importModule,
51
+ isString,
43
52
  makeFqName,
44
53
  maybeExtends,
45
54
  registerInitFunction,
@@ -51,10 +60,14 @@ import { URI } from 'vscode-uri';
51
60
  import { AstNode, LangiumCoreServices, LangiumDocument } from 'langium';
52
61
  import { isNodeEnv, path } from '../utils/runtime.js';
53
62
  import { CoreModules, registerCoreModules } from './modules/core.js';
54
- import { parse, parseModule } from '../language/parser.js';
63
+ import { parse, parseModule, parseWorkflow } from '../language/parser.js';
55
64
  import { logger } from './logger.js';
56
65
  import { Environment, evaluateStatements, GlobalEnvironment } from './interpreter.js';
57
66
  import { createPermission, createRole } from './modules/auth.js';
67
+ import { AgentEntityName, CoreAIModuleName, LlmEntityName } from './modules/ai.js';
68
+ import { GenericResolver, GenericResolverMethods } from './resolvers/interface.js';
69
+ import { registerResolver, setResolver, setSubscription } from './resolvers/registry.js';
70
+ import { ConfigSchema } from './state.js';
58
71
 
59
72
  export async function extractDocument(
60
73
  fileName: string,
@@ -231,7 +244,7 @@ export async function loadCoreModules() {
231
244
  registerCoreModules();
232
245
  }
233
246
  for (let i = 0; i < CoreModules.length; ++i) {
234
- internModule(await parseModule(CoreModules[i]));
247
+ await internModule(await parseModule(CoreModules[i]));
235
248
  }
236
249
  }
237
250
 
@@ -248,7 +261,7 @@ async function loadModule(fileName: string, fsOptions?: any, callback?: Function
248
261
 
249
262
  // Extract the AST node
250
263
  const module = await extractAstNode<ModuleDefinition>(fileName, services);
251
- const result: Module = internModule(module);
264
+ const result: Module = await internModule(module);
252
265
  console.log(chalk.green(`Module ${chalk.bold(result.name)} loaded`));
253
266
  logger.info(`Module ${result.name} loaded`);
254
267
  if (callback) {
@@ -295,25 +308,8 @@ function getFsAdapter(fs: any) {
295
308
  }
296
309
 
297
310
  function setRbacForEntity(entity: Entity, rbacSpec: RbacSpecDefinition) {
298
- const rbac: RbacSpecification[] = new Array<RbacSpecification>();
299
- rbacSpec.specEntries.forEach((specEntries: RbacSpecEntries) => {
300
- const rs: RbacSpecification = new RbacSpecification().setResource(
301
- makeFqName(entity.moduleName, entity.name)
302
- );
303
- specEntries.entries.forEach((spec: RbacSpecEntry) => {
304
- if (spec.allow) {
305
- rs.setPermissions(
306
- spec.allow.oprs.map((v: RbacOpr) => {
307
- return v.value;
308
- })
309
- );
310
- } else if (spec.role) {
311
- rs.setRoles(spec.role.roles);
312
- } else if (spec.expr) {
313
- rs.setExpression(spec.expr.lhs, spec.expr.rhs);
314
- }
315
- });
316
- rbac.push(rs);
311
+ const rbac: RbacSpecification[] = rbacSpec.specEntries.map((rs: RbacSpecEntries) => {
312
+ return RbacSpecification.from(rs).setResource(makeFqName(entity.moduleName, entity.name));
317
313
  });
318
314
  if (rbac.length > 0) {
319
315
  const f = async () => {
@@ -414,13 +410,112 @@ export async function runStandaloneStatements() {
414
410
  }
415
411
  }
416
412
 
417
- export function addFromDef(def: Definition, moduleName: string) {
413
+ async function addAgentDefinition(def: AgentDefinition, moduleName: string) {
414
+ let llmName: string | undefined = undefined;
415
+ const name = def.name;
416
+ let hasUserLlm = false;
417
+ const attrsStrs = new Array<string>();
418
+ attrsStrs.push(`name "${name}"`);
419
+ const attrs = newInstanceAttributes();
420
+ def.body?.attributes.forEach((sa: SetAttribute) => {
421
+ let v: any = undefined;
422
+ if (isLiteral(sa.value)) {
423
+ v = sa.value.str || sa.value.id || sa.value.num;
424
+ if (v == undefined) {
425
+ v = sa.value.bool;
426
+ }
427
+ }
428
+ if (v == undefined) {
429
+ throw new Error(`Cannot initialize agent ${name}, only literals can be set for attributes`);
430
+ }
431
+ if (llmName == undefined && sa.name == 'llm') {
432
+ llmName = v;
433
+ hasUserLlm = true;
434
+ }
435
+ const ov = v;
436
+ if (isLiteral(sa.value) && (sa.value.str || sa.value.id)) {
437
+ v = `"${v}"`;
438
+ }
439
+ attrsStrs.push(`${sa.name} ${v}`);
440
+ attrs.set(sa.name, ov);
441
+ });
442
+ if (!attrs.has('llm')) {
443
+ llmName = `${name}_llm`;
444
+ attrsStrs.push(`llm "${llmName}"`);
445
+ if (hasUserLlm) attrs.set('llm', llmName);
446
+ }
447
+ const createAgent = `{${CoreAIModuleName}/${AgentEntityName} {
448
+ ${attrsStrs.join(',')}
449
+ }, @upsert}`;
450
+ let wf = createAgent;
451
+ if (llmName) {
452
+ wf = `{${CoreAIModuleName}/${LlmEntityName} {name "${llmName}"}, @upsert}; ${wf}`;
453
+ }
454
+ (await parseWorkflow(`workflow A {${wf}}`)).statements.forEach((stmt: Statement) => {
455
+ addStandaloneStatement(stmt, moduleName);
456
+ });
457
+ addAgent(def.name, attrs, moduleName);
458
+ }
459
+
460
+ function addResolverDefinition(def: ResolverDefinition, moduleName: string) {
461
+ const resolverName = `${moduleName}/${def.name}`;
462
+ const paths = def.paths;
463
+ if (paths.length == 0) {
464
+ logger.warn(`Resolver has no associated paths - ${resolverName}`);
465
+ return;
466
+ }
467
+ registerInitFunction(() => {
468
+ const methods = new Map<string, Function>();
469
+ let subsFn: Function | undefined;
470
+ let subsEvent: string | undefined;
471
+ def.methods.forEach((spec: ResolverMethodSpec) => {
472
+ const n = spec.key.name;
473
+ if (n == 'subscribe') {
474
+ subsFn = asResolverFn(spec.fn.name);
475
+ } else if (n == 'onSubscription') {
476
+ subsEvent = spec.fn.name;
477
+ } else {
478
+ methods.set(n, asResolverFn(spec.fn.name));
479
+ }
480
+ });
481
+ const methodsObj = Object.fromEntries(methods.entries()) as GenericResolverMethods;
482
+ const resolver = new GenericResolver(resolverName, methodsObj);
483
+ registerResolver(resolverName, () => {
484
+ return resolver;
485
+ });
486
+ paths.forEach((path: string) => {
487
+ setResolver(path, resolverName);
488
+ });
489
+ if (subsFn && subsEvent) {
490
+ resolver.subs = {
491
+ subscribe: subsFn,
492
+ onSubscriptionEvent: subsEvent,
493
+ };
494
+ setSubscription(subsEvent, resolverName);
495
+ resolver.subscribe();
496
+ }
497
+ });
498
+ }
499
+
500
+ function asResolverFn(fname: string): Function {
501
+ let fn = getModuleFn(fname);
502
+ if (fn) return fn;
503
+ fn = eval(fname);
504
+ if (!(fn instanceof Function)) {
505
+ throw new Error(`${fname} is not a function`);
506
+ }
507
+ return fn as Function;
508
+ }
509
+
510
+ export async function addFromDef(def: Definition, moduleName: string) {
418
511
  if (isEntityDefinition(def)) addSchemaFromDef(def, moduleName);
419
512
  else if (isEventDefinition(def)) addSchemaFromDef(def, moduleName);
420
513
  else if (isRecordDefinition(def)) addSchemaFromDef(def, moduleName);
421
514
  else if (isRelationshipDefinition(def)) addRelationshipFromDef(def, moduleName);
422
515
  else if (isWorkflowDefinition(def)) addWorkflowFromDef(def, moduleName);
516
+ else if (isAgentDefinition(def)) await addAgentDefinition(def, moduleName);
423
517
  else if (isStandaloneStatement(def)) addStandaloneStatement(def.stmt, moduleName);
518
+ else if (isResolverDefinition(def)) addResolverDefinition(def, moduleName);
424
519
  }
425
520
 
426
521
  export async function parseAndIntern(code: string, moduleName?: string) {
@@ -434,17 +529,51 @@ export async function parseAndIntern(code: string, moduleName?: string) {
434
529
  if (r.parseResult.parserErrors.length > 0) {
435
530
  throw new Error(`Parser errors: ${r.parseResult.parserErrors.join('\n')}`);
436
531
  }
437
- internModule(r.parseResult.value);
532
+ await internModule(r.parseResult.value);
438
533
  }
439
534
 
440
- export function internModule(module: ModuleDefinition): Module {
535
+ export async function internModule(module: ModuleDefinition): Promise<Module> {
441
536
  const mn = module.name;
442
537
  const r = addModule(mn);
443
538
  module.imports.forEach(async (imp: Import) => {
444
539
  await importModule(imp.path, imp.name);
445
540
  });
446
- module.defs.forEach((def: Definition) => {
447
- addFromDef(def, mn);
448
- });
541
+ for (let i = 0; i < module.defs.length; ++i) {
542
+ const def = module.defs[i];
543
+ await addFromDef(def, mn);
544
+ }
449
545
  return r;
450
546
  }
547
+
548
+ const JS_PREFIX = '#js';
549
+
550
+ function preprocessRawConfig(rawConfig: any): any {
551
+ const keys = Object.keys(rawConfig);
552
+ keys.forEach((k: any) => {
553
+ const v = rawConfig[k];
554
+ if (isString(v) && v.startsWith(JS_PREFIX)) {
555
+ const s = v.substring(3).trim();
556
+ rawConfig[k] = eval(s);
557
+ } else if (typeof v == 'object') {
558
+ preprocessRawConfig(v);
559
+ }
560
+ });
561
+ return rawConfig;
562
+ }
563
+
564
+ export async function loadRawConfig(
565
+ configFileName: string,
566
+ validate: boolean = true,
567
+ fsOptions?: any
568
+ ): Promise<any> {
569
+ const fs = await getFileSystem(fsOptions);
570
+ let rawConfig = preprocessRawConfig(JSON.parse(await fs.readFile(configFileName)));
571
+ if (validate) {
572
+ rawConfig = ConfigSchema.parse(rawConfig);
573
+ }
574
+ return rawConfig;
575
+ }
576
+
577
+ export function generateRawConfig(configObj: any): string {
578
+ return JSON.stringify(configObj);
579
+ }