agentlang 0.0.3 → 0.0.5

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 (122) hide show
  1. package/README.md +16 -47
  2. package/out/api/http.d.ts.map +1 -1
  3. package/out/api/http.js +39 -19
  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 +98 -19
  10. package/out/language/generated/ast.d.ts.map +1 -1
  11. package/out/language/generated/ast.js +144 -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 +1000 -305
  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 +1097 -312
  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 +164 -29
  46. package/out/runtime/loader.js.map +1 -1
  47. package/out/runtime/module.d.ts +49 -5
  48. package/out/runtime/module.d.ts.map +1 -1
  49. package/out/runtime/module.js +214 -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 +295 -32
  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/resolvers/sqldb/database.d.ts +4 -2
  74. package/out/runtime/resolvers/sqldb/database.d.ts.map +1 -1
  75. package/out/runtime/resolvers/sqldb/database.js +43 -4
  76. package/out/runtime/resolvers/sqldb/database.js.map +1 -1
  77. package/out/runtime/resolvers/sqldb/impl.d.ts.map +1 -1
  78. package/out/runtime/resolvers/sqldb/impl.js +7 -3
  79. package/out/runtime/resolvers/sqldb/impl.js.map +1 -1
  80. package/out/runtime/state.d.ts +31 -3
  81. package/out/runtime/state.d.ts.map +1 -1
  82. package/out/runtime/state.js +11 -1
  83. package/out/runtime/state.js.map +1 -1
  84. package/out/runtime/util.d.ts +5 -0
  85. package/out/runtime/util.d.ts.map +1 -1
  86. package/out/runtime/util.js +27 -0
  87. package/out/runtime/util.js.map +1 -1
  88. package/out/syntaxes/agentlang.monarch.js +2 -2
  89. package/out/syntaxes/agentlang.monarch.js.map +1 -1
  90. package/out/utils/http.d.ts +2 -0
  91. package/out/utils/http.d.ts.map +1 -0
  92. package/out/utils/http.js +5 -0
  93. package/out/utils/http.js.map +1 -0
  94. package/package.json +8 -6
  95. package/src/api/http.ts +41 -17
  96. package/src/cli/main.ts +6 -12
  97. package/src/language/agentlang.langium +35 -10
  98. package/src/language/generated/ast.ts +257 -45
  99. package/src/language/generated/grammar.ts +1000 -305
  100. package/src/language/generated/module.ts +1 -1
  101. package/src/language/parser.ts +12 -8
  102. package/src/runtime/agents/common.ts +1 -1
  103. package/src/runtime/auth/cognito.ts +605 -74
  104. package/src/runtime/auth/defs.ts +17 -1
  105. package/src/runtime/auth/interface.ts +6 -1
  106. package/src/runtime/defs.ts +45 -0
  107. package/src/runtime/interpreter.ts +43 -34
  108. package/src/runtime/loader.ts +172 -30
  109. package/src/runtime/module.ts +257 -10
  110. package/src/runtime/modules/ai.ts +52 -28
  111. package/src/runtime/modules/auth.ts +343 -40
  112. package/src/runtime/modules/core.ts +3 -1
  113. package/src/runtime/relgraph.ts +2 -8
  114. package/src/runtime/resolvers/interface.ts +141 -6
  115. package/src/runtime/resolvers/registry.ts +5 -2
  116. package/src/runtime/resolvers/sqldb/database.ts +55 -4
  117. package/src/runtime/resolvers/sqldb/impl.ts +8 -7
  118. package/src/runtime/state.ts +11 -1
  119. package/src/runtime/util.ts +29 -0
  120. package/src/syntaxes/agentlang.monarch.ts +2 -2
  121. package/src/utils/http.ts +5 -0
  122. 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,12 @@ import {
19
17
  Statement,
20
18
  isStandaloneStatement,
21
19
  SchemaDefinition,
20
+ isAgentDefinition,
21
+ AgentDefinition,
22
+ isResolverDefinition,
23
+ ResolverDefinition,
24
+ ResolverMethodSpec,
25
+ AgentPropertyDef,
22
26
  } from '../language/generated/ast.js';
23
27
  import {
24
28
  addEntity,
@@ -36,10 +40,14 @@ import {
36
40
  isModule,
37
41
  getUserModuleNames,
38
42
  removeModule,
43
+ newInstanceAttributes,
44
+ addAgent,
39
45
  } from './module.js';
40
46
  import {
41
47
  findRbacSchema,
48
+ getModuleFn,
42
49
  importModule,
50
+ isString,
43
51
  makeFqName,
44
52
  maybeExtends,
45
53
  registerInitFunction,
@@ -51,10 +59,14 @@ import { URI } from 'vscode-uri';
51
59
  import { AstNode, LangiumCoreServices, LangiumDocument } from 'langium';
52
60
  import { isNodeEnv, path } from '../utils/runtime.js';
53
61
  import { CoreModules, registerCoreModules } from './modules/core.js';
54
- import { parse, parseModule } from '../language/parser.js';
62
+ import { parse, parseModule, parseWorkflow } from '../language/parser.js';
55
63
  import { logger } from './logger.js';
56
64
  import { Environment, evaluateStatements, GlobalEnvironment } from './interpreter.js';
57
65
  import { createPermission, createRole } from './modules/auth.js';
66
+ import { AgentEntityName, CoreAIModuleName, LlmEntityName } from './modules/ai.js';
67
+ import { GenericResolver, GenericResolverMethods } from './resolvers/interface.js';
68
+ import { registerResolver, setResolver, setSubscription } from './resolvers/registry.js';
69
+ import { ConfigSchema } from './state.js';
58
70
 
59
71
  export async function extractDocument(
60
72
  fileName: string,
@@ -231,7 +243,7 @@ export async function loadCoreModules() {
231
243
  registerCoreModules();
232
244
  }
233
245
  for (let i = 0; i < CoreModules.length; ++i) {
234
- internModule(await parseModule(CoreModules[i]));
246
+ await internModule(await parseModule(CoreModules[i]));
235
247
  }
236
248
  }
237
249
 
@@ -248,7 +260,7 @@ async function loadModule(fileName: string, fsOptions?: any, callback?: Function
248
260
 
249
261
  // Extract the AST node
250
262
  const module = await extractAstNode<ModuleDefinition>(fileName, services);
251
- const result: Module = internModule(module);
263
+ const result: Module = await internModule(module);
252
264
  console.log(chalk.green(`Module ${chalk.bold(result.name)} loaded`));
253
265
  logger.info(`Module ${result.name} loaded`);
254
266
  if (callback) {
@@ -295,25 +307,8 @@ function getFsAdapter(fs: any) {
295
307
  }
296
308
 
297
309
  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);
310
+ const rbac: RbacSpecification[] = rbacSpec.specEntries.map((rs: RbacSpecEntries) => {
311
+ return RbacSpecification.from(rs).setResource(makeFqName(entity.moduleName, entity.name));
317
312
  });
318
313
  if (rbac.length > 0) {
319
314
  const f = async () => {
@@ -414,13 +409,126 @@ export async function runStandaloneStatements() {
414
409
  }
415
410
  }
416
411
 
417
- export function addFromDef(def: Definition, moduleName: string) {
412
+ async function addAgentDefinition(def: AgentDefinition, moduleName: string) {
413
+ let llmName: string | undefined = undefined;
414
+ const name = def.name;
415
+ let hasUserLlm = false;
416
+ const attrsStrs = new Array<string>();
417
+ attrsStrs.push(`name "${name}"`);
418
+ const attrs = newInstanceAttributes();
419
+ def.body?.attributes.forEach((apdef: AgentPropertyDef) => {
420
+ let v: any = undefined;
421
+ if (apdef.value.array) {
422
+ v = apdef.value.array.vals
423
+ .map((stmt: Statement) => {
424
+ if (stmt.pattern.literal) {
425
+ const s = stmt.pattern.literal.str;
426
+ if (s == undefined) {
427
+ throw new Error(`Only arrays of string-literals are to be passed to agent ${name}`);
428
+ }
429
+ return s;
430
+ } else {
431
+ throw new Error(`Invalid value in array passed to agent ${name}`);
432
+ }
433
+ })
434
+ .join(',');
435
+ } else {
436
+ v = apdef.value.str || apdef.value.id || apdef.value.num;
437
+ if (v == undefined) {
438
+ v = apdef.value.bool;
439
+ }
440
+ }
441
+ if (v == undefined) {
442
+ throw new Error(`Cannot initialize agent ${name}, only literals can be set for attributes`);
443
+ }
444
+ if (llmName == undefined && apdef.name == 'llm') {
445
+ llmName = v;
446
+ hasUserLlm = true;
447
+ }
448
+ const ov = v;
449
+ if (apdef.value.str || apdef.value.id || apdef.value.array) {
450
+ v = `"${v}"`;
451
+ }
452
+ attrsStrs.push(`${apdef.name} ${v}`);
453
+ attrs.set(apdef.name, ov);
454
+ });
455
+ if (!attrs.has('llm')) {
456
+ llmName = `${name}_llm`;
457
+ attrsStrs.push(`llm "${llmName}"`);
458
+ if (hasUserLlm) attrs.set('llm', llmName);
459
+ }
460
+ const createAgent = `{${CoreAIModuleName}/${AgentEntityName} {
461
+ ${attrsStrs.join(',')}
462
+ }, @upsert}`;
463
+ let wf = createAgent;
464
+ if (llmName) {
465
+ wf = `{${CoreAIModuleName}/${LlmEntityName} {name "${llmName}"}, @upsert}; ${wf}`;
466
+ }
467
+ (await parseWorkflow(`workflow A {${wf}}`)).statements.forEach((stmt: Statement) => {
468
+ addStandaloneStatement(stmt, moduleName);
469
+ });
470
+ addAgent(def.name, attrs, moduleName);
471
+ }
472
+
473
+ function addResolverDefinition(def: ResolverDefinition, moduleName: string) {
474
+ const resolverName = `${moduleName}/${def.name}`;
475
+ const paths = def.paths;
476
+ if (paths.length == 0) {
477
+ logger.warn(`Resolver has no associated paths - ${resolverName}`);
478
+ return;
479
+ }
480
+ registerInitFunction(() => {
481
+ const methods = new Map<string, Function>();
482
+ let subsFn: Function | undefined;
483
+ let subsEvent: string | undefined;
484
+ def.methods.forEach((spec: ResolverMethodSpec) => {
485
+ const n = spec.key.name;
486
+ if (n == 'subscribe') {
487
+ subsFn = asResolverFn(spec.fn.name);
488
+ } else if (n == 'onSubscription') {
489
+ subsEvent = spec.fn.name;
490
+ } else {
491
+ methods.set(n, asResolverFn(spec.fn.name));
492
+ }
493
+ });
494
+ const methodsObj = Object.fromEntries(methods.entries()) as GenericResolverMethods;
495
+ const resolver = new GenericResolver(resolverName, methodsObj);
496
+ registerResolver(resolverName, () => {
497
+ return resolver;
498
+ });
499
+ paths.forEach((path: string) => {
500
+ setResolver(path, resolverName);
501
+ });
502
+ if (subsFn && subsEvent) {
503
+ resolver.subs = {
504
+ subscribe: subsFn,
505
+ onSubscriptionEvent: subsEvent,
506
+ };
507
+ setSubscription(subsEvent, resolverName);
508
+ resolver.subscribe();
509
+ }
510
+ });
511
+ }
512
+
513
+ function asResolverFn(fname: string): Function {
514
+ let fn = getModuleFn(fname);
515
+ if (fn) return fn;
516
+ fn = eval(fname);
517
+ if (!(fn instanceof Function)) {
518
+ throw new Error(`${fname} is not a function`);
519
+ }
520
+ return fn as Function;
521
+ }
522
+
523
+ export async function addFromDef(def: Definition, moduleName: string) {
418
524
  if (isEntityDefinition(def)) addSchemaFromDef(def, moduleName);
419
525
  else if (isEventDefinition(def)) addSchemaFromDef(def, moduleName);
420
526
  else if (isRecordDefinition(def)) addSchemaFromDef(def, moduleName);
421
527
  else if (isRelationshipDefinition(def)) addRelationshipFromDef(def, moduleName);
422
528
  else if (isWorkflowDefinition(def)) addWorkflowFromDef(def, moduleName);
529
+ else if (isAgentDefinition(def)) await addAgentDefinition(def, moduleName);
423
530
  else if (isStandaloneStatement(def)) addStandaloneStatement(def.stmt, moduleName);
531
+ else if (isResolverDefinition(def)) addResolverDefinition(def, moduleName);
424
532
  }
425
533
 
426
534
  export async function parseAndIntern(code: string, moduleName?: string) {
@@ -434,17 +542,51 @@ export async function parseAndIntern(code: string, moduleName?: string) {
434
542
  if (r.parseResult.parserErrors.length > 0) {
435
543
  throw new Error(`Parser errors: ${r.parseResult.parserErrors.join('\n')}`);
436
544
  }
437
- internModule(r.parseResult.value);
545
+ await internModule(r.parseResult.value);
438
546
  }
439
547
 
440
- export function internModule(module: ModuleDefinition): Module {
548
+ export async function internModule(module: ModuleDefinition): Promise<Module> {
441
549
  const mn = module.name;
442
550
  const r = addModule(mn);
443
551
  module.imports.forEach(async (imp: Import) => {
444
552
  await importModule(imp.path, imp.name);
445
553
  });
446
- module.defs.forEach((def: Definition) => {
447
- addFromDef(def, mn);
448
- });
554
+ for (let i = 0; i < module.defs.length; ++i) {
555
+ const def = module.defs[i];
556
+ await addFromDef(def, mn);
557
+ }
449
558
  return r;
450
559
  }
560
+
561
+ const JS_PREFIX = '#js';
562
+
563
+ function preprocessRawConfig(rawConfig: any): any {
564
+ const keys = Object.keys(rawConfig);
565
+ keys.forEach((k: any) => {
566
+ const v = rawConfig[k];
567
+ if (isString(v) && v.startsWith(JS_PREFIX)) {
568
+ const s = v.substring(3).trim();
569
+ rawConfig[k] = eval(s);
570
+ } else if (typeof v == 'object') {
571
+ preprocessRawConfig(v);
572
+ }
573
+ });
574
+ return rawConfig;
575
+ }
576
+
577
+ export async function loadRawConfig(
578
+ configFileName: string,
579
+ validate: boolean = true,
580
+ fsOptions?: any
581
+ ): Promise<any> {
582
+ const fs = await getFileSystem(fsOptions);
583
+ let rawConfig = preprocessRawConfig(JSON.parse(await fs.readFile(configFileName)));
584
+ if (validate) {
585
+ rawConfig = ConfigSchema.parse(rawConfig);
586
+ }
587
+ return rawConfig;
588
+ }
589
+
590
+ export function generateRawConfig(configObj: any): string {
591
+ return JSON.stringify(configObj);
592
+ }