agentlang 0.0.10 → 0.0.11

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 (46) hide show
  1. package/out/language/generated/ast.d.ts +11 -2
  2. package/out/language/generated/ast.d.ts.map +1 -1
  3. package/out/language/generated/ast.js +15 -2
  4. package/out/language/generated/ast.js.map +1 -1
  5. package/out/language/generated/grammar.d.ts.map +1 -1
  6. package/out/language/generated/grammar.js +162 -119
  7. package/out/language/generated/grammar.js.map +1 -1
  8. package/out/language/main.cjs +174 -121
  9. package/out/language/main.cjs.map +2 -2
  10. package/out/language/syntax.js +2 -2
  11. package/out/language/syntax.js.map +1 -1
  12. package/out/runtime/agents/common.d.ts +1 -1
  13. package/out/runtime/agents/common.d.ts.map +1 -1
  14. package/out/runtime/agents/common.js +10 -10
  15. package/out/runtime/interpreter.d.ts +6 -0
  16. package/out/runtime/interpreter.d.ts.map +1 -1
  17. package/out/runtime/interpreter.js +26 -0
  18. package/out/runtime/interpreter.js.map +1 -1
  19. package/out/runtime/jsmodules.js +1 -1
  20. package/out/runtime/jsmodules.js.map +1 -1
  21. package/out/runtime/loader.d.ts.map +1 -1
  22. package/out/runtime/loader.js +5 -2
  23. package/out/runtime/loader.js.map +1 -1
  24. package/out/runtime/modules/ai.js +1 -1
  25. package/out/runtime/modules/auth.d.ts.map +1 -1
  26. package/out/runtime/modules/auth.js +21 -16
  27. package/out/runtime/modules/auth.js.map +1 -1
  28. package/out/runtime/modules/core.d.ts +3 -1
  29. package/out/runtime/modules/core.d.ts.map +1 -1
  30. package/out/runtime/modules/core.js +30 -3
  31. package/out/runtime/modules/core.js.map +1 -1
  32. package/out/syntaxes/agentlang.monarch.js +1 -1
  33. package/out/syntaxes/agentlang.monarch.js.map +1 -1
  34. package/package.json +1 -1
  35. package/src/language/agentlang.langium +7 -5
  36. package/src/language/generated/ast.ts +29 -5
  37. package/src/language/generated/grammar.ts +162 -119
  38. package/src/language/syntax.ts +2 -2
  39. package/src/runtime/agents/common.ts +10 -10
  40. package/src/runtime/interpreter.ts +29 -0
  41. package/src/runtime/jsmodules.ts +1 -1
  42. package/src/runtime/loader.ts +4 -1
  43. package/src/runtime/modules/ai.ts +1 -1
  44. package/src/runtime/modules/auth.ts +21 -17
  45. package/src/runtime/modules/core.ts +38 -3
  46. package/src/syntaxes/agentlang.monarch.ts +1 -1
@@ -39,9 +39,9 @@ export class BasePattern {
39
39
 
40
40
  private aliasesAsString(): string | undefined {
41
41
  if (this.alias) {
42
- return ` as ${this.alias}`;
42
+ return ` @as ${this.alias}`;
43
43
  } else if (this.aliases) {
44
- return ` as [${this.aliases.join(',')}]`;
44
+ return ` @as [${this.aliases.join(',')}]`;
45
45
  } else {
46
46
  return undefined;
47
47
  }
@@ -92,24 +92,24 @@ Note the value passed to the 'salary' attribute - it's an arithmetic expression.
92
92
  A successful query pattern will return an array of instances. The 'for' pattern can be used to iterate over an array. An example follows:
93
93
 
94
94
  workflow NotifyEmployees {
95
- {Erp/Employee {salary?> 1000}} as employees;
95
+ {Erp/Employee {salary?> 1000}} @as employees;
96
96
  for emp in employees {
97
97
  {Erp/SendMail {email emp.email, body "You are selected for an increment!"}}
98
98
  }
99
99
  }
100
100
 
101
- Also note the use of the 'as' keyword - this binds the result of a pattern to an 'alias'. Here the result of the query is bound to the
101
+ Also note the use of the '@as' keyword - this binds the result of a pattern to an 'alias'. Here the result of the query is bound to the
102
102
  alias named 'employees'. Any pattern can have an alias, including 'if' and 'for'. An alias can be used to refer to the attributes of the instance,
103
103
  via the dot(.) notation. Aliases can also be used to destructure a query result - here's an example:
104
104
 
105
105
  workflow FindFirstTwoEmployees {
106
- {Erp/Employee {salary?> 1000}} as [emp1, emp2];
106
+ {Erp/Employee {salary?> 1000}} @as [emp1, emp2];
107
107
  [emp1, emp2]
108
108
  }
109
109
 
110
110
  This alias will bind the first two instances to 'a' and 'b' and the rest of the instances to an array named 'xs':
111
111
 
112
- {SomeEntity {id?> 1}} as [a, b, _, xs]
112
+ {SomeEntity {id?> 1}} @as [a, b, _, xs]
113
113
 
114
114
  Examples of binding aliases to 'if' and 'for':
115
115
 
@@ -117,11 +117,11 @@ if (IncrementSalary.percentage > 10) {
117
117
  {Erp/Employee {employeeId IncrementSalary.employeeId, salary salary + salary * IncrementSalary.percentage}}
118
118
  } else {
119
119
  {Erp/Employee {employeeId IncrementSalary.employeeId, salary salary + 1500}}
120
- } as emp
120
+ } @as emp
121
121
 
122
122
  for emp in employees {
123
123
  {Erp/SendMail {email emp.email, body "You are selected for an increment!"}}
124
- } as emails
124
+ } @as emails
125
125
 
126
126
  Make sure all references based on a preceding pattern is based either on an actual alias or the name of the workflow. For example, the following sequence of patterns
127
127
  are invalid, because the alias 'employee' is not defined:
@@ -131,7 +131,7 @@ are invalid, because the alias 'employee' is not defined:
131
131
 
132
132
  A fix for the reference-error is shown below:
133
133
 
134
- {Employee {id? 101}} as employee;
134
+ {Employee {id? 101}} @as employee;
135
135
  {SendEmail {to employee.email, body "hello"}}
136
136
 
137
137
  Entities in a module can be connected together in relationships. There are two types of relationships - 'contains' and 'between'.
@@ -198,7 +198,7 @@ fill-in values from the available context. For example, if your instruction is "
198
198
  'please call me as soon as possible'", the best workflow to return is:
199
199
 
200
200
  workflow sendEmail {
201
- {employee {id? 101}} as emp;
201
+ {employee {id? 101}} @as emp;
202
202
  {email {to emp.email body "please call me as soon as possible"}}
203
203
  }
204
204
 
@@ -206,7 +206,7 @@ because all the information needed is available in the context. If the instructi
206
206
  'please call me as soon as possible'", then you can return:
207
207
 
208
208
  workflow sendEmail {
209
- {employee {id? sendEmail.employeeId}} as emp;
209
+ {employee {id? sendEmail.employeeId}} @as emp;
210
210
  {email {to emp.email body "please call me as soon as possible"}}
211
211
  }
212
212
 
@@ -215,7 +215,7 @@ The point is use the immediate context to fill-in values in generated patterns,
215
215
  Also generate a workflow only if required explicitly by the user or the contextual information is incomplete. Otherwise, just return an array of patterns.
216
216
  As an example, if the user request is "send an email to employee 101 with this message - 'please call me as soon as possible'", you must return:
217
217
 
218
- [{employee {id? 101}} as emp;
218
+ [{employee {id? 101}} @as emp;
219
219
  {email {to emp.email, body "please call me as soon as possible"}}]
220
220
 
221
221
  Note that each pattern in the array is separated by a ; and not a comma(,).
@@ -114,6 +114,7 @@ export class Environment extends Instance {
114
114
  private activeUser: string = AdminUserId;
115
115
  private activeUserSet: boolean = false;
116
116
  private lastResult: Result;
117
+ private returnFlag: boolean = false;
117
118
  private parentPath: string | undefined;
118
119
  private normalizedParentPath: string | undefined;
119
120
  private betweenRelInfo: BetweenRelInfo | undefined;
@@ -222,6 +223,17 @@ export class Environment extends Instance {
222
223
  return this;
223
224
  }
224
225
 
226
+ static SuspensionUserData = '^';
227
+
228
+ bindSuspensionUserData(userData: string): Environment {
229
+ this.bind(Environment.SuspensionUserData, userData);
230
+ return this;
231
+ }
232
+
233
+ lookupSuspensionUserData(): string | undefined {
234
+ return this.lookup(Environment.SuspensionUserData);
235
+ }
236
+
225
237
  maybeLookupAgentInstance(entryName: string): Instance | undefined {
226
238
  const v = this.lookup(entryName);
227
239
  if (v && isInstanceOfType(v, AgentFqName)) {
@@ -263,6 +275,18 @@ export class Environment extends Instance {
263
275
  }
264
276
  }
265
277
 
278
+ markForReturn(): Environment {
279
+ if (this.parent) {
280
+ this.parent.markForReturn();
281
+ }
282
+ this.returnFlag = true;
283
+ return this;
284
+ }
285
+
286
+ isMarkedForReturn(): boolean {
287
+ return this.returnFlag;
288
+ }
289
+
266
290
  protected propagateSuspension(suspId: string) {
267
291
  this.suspensionId = suspId;
268
292
  if (this.parent) {
@@ -597,6 +621,8 @@ export async function evaluateStatements(
597
621
  env.setLastResult({ suspension: suspId || 'null' });
598
622
  break;
599
623
  }
624
+ } else if (env.isMarkedForReturn()) {
625
+ break;
600
626
  }
601
627
  }
602
628
  if (continuation != undefined) {
@@ -735,6 +761,9 @@ async function evaluatePattern(pat: Pattern, env: Environment): Promise<void> {
735
761
  await evaluatePurge(pat.purge, env);
736
762
  } else if (pat.fullTextSearch) {
737
763
  await evaluateFullTextSearch(pat.fullTextSearch, env);
764
+ } else if (pat.return) {
765
+ await evaluatePattern(pat.return.pat, env);
766
+ env.markForReturn();
738
767
  }
739
768
  }
740
769
 
@@ -17,7 +17,7 @@ export async function importModule(path: string, name: string, moduleFileName?:
17
17
  }
18
18
  path = `${s}${sep}${path}`;
19
19
  }
20
- if (!(path.startsWith(sep) || path.startsWith('.'))) {
20
+ if ((path.startsWith(sep) || path.startsWith('.')) && moduleFileName) {
21
21
  path = process.cwd() + sep + path;
22
22
  }
23
23
  const m = await import(/* @vite-ignore */ path);
@@ -45,6 +45,7 @@ import {
45
45
  addAgent,
46
46
  } from './module.js';
47
47
  import {
48
+ escapeSpecialChars,
48
49
  findRbacSchema,
49
50
  isString,
50
51
  makeFqName,
@@ -446,8 +447,10 @@ async function addAgentDefinition(def: AgentDefinition, moduleName: string) {
446
447
  hasUserLlm = true;
447
448
  }
448
449
  const ov = v;
449
- if (apdef.value.str || apdef.value.id || apdef.value.array) {
450
+ if (apdef.value.id || apdef.value.array) {
450
451
  v = `"${v}"`;
452
+ } else if (apdef.value.str) {
453
+ v = `"${escapeSpecialChars(v)}"`;
451
454
  }
452
455
  attrsStrs.push(`${apdef.name} ${v}`);
453
456
  attrs.set(apdef.name, ov);
@@ -43,7 +43,7 @@ entity agentChatSession {
43
43
  }
44
44
 
45
45
  workflow findAgentChatSession {
46
- {agentChatSession {id? findAgentChatSession.id}} as [sess];
46
+ {agentChatSession {id? findAgentChatSession.id}} @as [sess];
47
47
  sess
48
48
  }
49
49
 
@@ -29,7 +29,7 @@ export const CoreAuthModuleName = makeCoreModuleName('auth');
29
29
 
30
30
  export default `module ${CoreAuthModuleName}
31
31
 
32
- import "./modules/auth.js" as Auth
32
+ import "./modules/auth.js" @as Auth
33
33
 
34
34
  entity User {
35
35
  id UUID @id @default(uuid()),
@@ -52,12 +52,12 @@ workflow CreateUser {
52
52
  }
53
53
 
54
54
  workflow FindUser {
55
- {User {id? FindUser.id}} as [user];
55
+ {User {id? FindUser.id}} @as [user];
56
56
  user
57
57
  }
58
58
 
59
59
  workflow FindUserByEmail {
60
- {User {email? FindUserByEmail.email}} as [user];
60
+ {User {email? FindUserByEmail.email}} @as [user];
61
61
  user
62
62
  }
63
63
 
@@ -83,19 +83,19 @@ workflow CreateRole {
83
83
  }
84
84
 
85
85
  workflow FindRole {
86
- {Role {name? FindRole.name}} as [role];
86
+ {Role {name? FindRole.name}} @as [role];
87
87
  role
88
88
  }
89
89
 
90
90
  workflow AssignUserToRole {
91
- {User {id? AssignUserToRole.userId}} as [user];
92
- {Role {name? AssignUserToRole.roleName}} as [role];
91
+ {User {id? AssignUserToRole.userId}} @as [user];
92
+ {Role {name? AssignUserToRole.roleName}} @as [role];
93
93
  {UserRole {User user, Role role}, @upsert}
94
94
  }
95
95
 
96
96
  workflow AssignUserToRoleByEmail {
97
- {User {email? AssignUserToRoleByEmail.email}} as [user];
98
- {Role {name? AssignUserToRoleByEmail.roleName}} as [role];
97
+ {User {email? AssignUserToRoleByEmail.email}} @as [user];
98
+ {Role {name? AssignUserToRoleByEmail.roleName}} @as [role];
99
99
  {UserRole {User user, Role role}, @upsert}
100
100
  }
101
101
 
@@ -116,8 +116,8 @@ workflow CreatePermission {
116
116
  }
117
117
 
118
118
  workflow AddPermissionToRole {
119
- {Role {name? AddPermissionToRole.roleName}} as role;
120
- {Permission {id? AddPermissionToRole.permissionId}} as perm;
119
+ {Role {name? AddPermissionToRole.roleName}} @as role;
120
+ {Permission {id? AddPermissionToRole.permissionId}} @as perm;
121
121
  {RolePermission {Role role, Permission perm}, @upsert}
122
122
  }
123
123
 
@@ -154,12 +154,12 @@ workflow UpdateSession {
154
154
  }
155
155
 
156
156
  workflow FindSession {
157
- {Session {id? FindSession.id}} as [session];
157
+ {Session {id? FindSession.id}} @as [session];
158
158
  session
159
159
  }
160
160
 
161
161
  workflow FindUserSession {
162
- {Session {userId? FindUserSession.userId}} as [session];
162
+ {Session {userId? FindUserSession.userId}} @as [session];
163
163
  session
164
164
  }
165
165
 
@@ -168,7 +168,7 @@ workflow RemoveSession {
168
168
  }
169
169
 
170
170
  workflow RemoveUserSession {
171
- {Session {userId? RemoveUserSession.id}} as [session];
171
+ {Session {userId? RemoveUserSession.id}} @as [session];
172
172
  purge {Session {id? session.id}}
173
173
  }
174
174
 
@@ -837,10 +837,14 @@ export async function refreshUserToken(refreshToken: string, env: Environment):
837
837
  }
838
838
 
839
839
  export function requireAuth(moduleName: string, eventName: string): boolean {
840
- const f =
841
- moduleName == CoreAuthModuleName &&
842
- (eventName == 'login' || eventName == 'signup' || eventName == 'refreshToken');
843
- return !f;
840
+ if (isAuthEnabled()) {
841
+ const f =
842
+ moduleName == CoreAuthModuleName &&
843
+ (eventName == 'login' || eventName == 'signup' || eventName == 'refreshToken');
844
+ return !f;
845
+ } else {
846
+ return false;
847
+ }
844
848
  }
845
849
 
846
850
  // Export getHttpStatusForError for use in HTTP handlers
@@ -11,10 +11,12 @@ import {
11
11
  import { logger } from '../logger.js';
12
12
  import { Statement } from '../../language/generated/ast.js';
13
13
  import { parseStatements } from '../../language/parser.js';
14
+ import { Resolver } from '../resolvers/interface.js';
15
+ import { PathAttributeName } from '../defs.js';
14
16
 
15
17
  const CoreModuleDefinition = `module ${DefaultModuleName}
16
18
 
17
- import "./modules/core.js" as Core
19
+ import "./modules/core.js" @as Core
18
20
 
19
21
  entity timer {
20
22
  name String @id,
@@ -42,6 +44,14 @@ entity suspension {
42
44
  createdBy String
43
45
  }
44
46
 
47
+ entity activeSuspension {
48
+ id UUID @id
49
+ }
50
+
51
+ resolver servicenow ["${DefaultModuleName}/activeSuspension"] {
52
+ query Core.lookupActiveSuspension
53
+ }
54
+
45
55
  workflow createSuspension {
46
56
  {suspension
47
57
  {id createSuspension.id
@@ -51,7 +61,7 @@ workflow createSuspension {
51
61
  }
52
62
 
53
63
  workflow restartSuspension {
54
- await Core.restartSuspension(restartSuspension.id)
64
+ await Core.restartSuspension(restartSuspension.id, restartSuspension.data)
55
65
  }
56
66
  `;
57
67
  export const CoreModules: string[] = [];
@@ -191,9 +201,14 @@ async function deleteSuspension(suspId: string, env?: Environment): Promise<any>
191
201
  }
192
202
  }
193
203
 
194
- export async function restartSuspension(suspId: string, env?: Environment): Promise<any> {
204
+ export async function restartSuspension(
205
+ suspId: string,
206
+ userData: string,
207
+ env?: Environment
208
+ ): Promise<any> {
195
209
  const susp = await loadSuspension(suspId, env);
196
210
  if (susp) {
211
+ susp.env.bindSuspensionUserData(userData);
197
212
  await evaluateStatements(susp.continuation, susp.env);
198
213
  await deleteSuspension(suspId, env);
199
214
  return susp.env.getLastResult();
@@ -202,3 +217,23 @@ export async function restartSuspension(suspId: string, env?: Environment): Prom
202
217
  return undefined;
203
218
  }
204
219
  }
220
+
221
+ export async function lookupActiveSuspension(
222
+ resolver: Resolver,
223
+ inst: Instance,
224
+ queryAll: boolean
225
+ ) {
226
+ if (!queryAll) {
227
+ const data = inst.lookupQueryVal(PathAttributeName).split('/')[1];
228
+ if (data) {
229
+ const parts = data.split(':');
230
+ const id = parts[0];
231
+ const userData = parts[1];
232
+ return await restartSuspension(id, userData, resolver.getEnvironment());
233
+ } else {
234
+ return [];
235
+ }
236
+ } else {
237
+ return [];
238
+ }
239
+ }
@@ -1,7 +1,7 @@
1
1
  // Monarch syntax highlighting for the agentlang language.
2
2
  export default {
3
3
  keywords: [
4
- '@actions','@after','@async','@before','@enum','@expr','@from','@meta','@oneof','@rbac','@ref','@upsert','@with_unique','agent','allow','and','as','await','between','catch','contains','create','delete','else','entity','error','event','extends','false','for','if','import','in','into','like','module','not','not_found','onSubscription','or','purge','query','read','record','relationship','resolver','roles','subscribe','true','update','upsert','where','workflow'
4
+ '@actions','@after','@as','@async','@before','@catch','@enum','@expr','@from','@meta','@oneof','@rbac','@ref','@upsert','@with_unique','agent','allow','and','await','between','contains','create','delete','else','entity','error','event','extends','false','for','if','import','in','into','like','module','not','not_found','onSubscription','or','purge','query','read','record','relationship','resolver','return','roles','subscribe','true','update','upsert','where','workflow'
5
5
  ],
6
6
  operators: [
7
7
  '*','+',',','-','.','/',':',';','<','<=','<>','=','>','>=','?','@'