agentlang 0.9.4 → 0.9.6

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 (105) hide show
  1. package/out/api/http.js +8 -2
  2. package/out/api/http.js.map +1 -1
  3. package/out/extension/main.cjs +253 -253
  4. package/out/extension/main.cjs.map +2 -2
  5. package/out/language/generated/ast.d.ts +1997 -151
  6. package/out/language/generated/ast.d.ts.map +1 -1
  7. package/out/language/generated/ast.js +2113 -1263
  8. package/out/language/generated/ast.js.map +1 -1
  9. package/out/language/generated/grammar.d.ts +1 -1
  10. package/out/language/generated/grammar.d.ts.map +1 -1
  11. package/out/language/generated/grammar.js +649 -762
  12. package/out/language/generated/grammar.js.map +1 -1
  13. package/out/language/generated/module.d.ts +1 -1
  14. package/out/language/generated/module.js +1 -1
  15. package/out/language/main.cjs +6401 -4072
  16. package/out/language/main.cjs.map +4 -4
  17. package/out/language/parser.js +8 -8
  18. package/out/language/parser.js.map +1 -1
  19. package/out/runtime/agents/common.d.ts +7 -1
  20. package/out/runtime/agents/common.d.ts.map +1 -1
  21. package/out/runtime/agents/common.js +101 -0
  22. package/out/runtime/agents/common.js.map +1 -1
  23. package/out/runtime/agents/impl/anthropic.js +4 -4
  24. package/out/runtime/agents/impl/anthropic.js.map +1 -1
  25. package/out/runtime/agents/impl/openai.js +4 -4
  26. package/out/runtime/agents/impl/openai.js.map +1 -1
  27. package/out/runtime/auth/defs.d.ts +1 -1
  28. package/out/runtime/auth/defs.js +1 -1
  29. package/out/runtime/defs.d.ts +1 -1
  30. package/out/runtime/defs.js +1 -1
  31. package/out/runtime/exec-graph.d.ts.map +1 -1
  32. package/out/runtime/exec-graph.js +5 -0
  33. package/out/runtime/exec-graph.js.map +1 -1
  34. package/out/runtime/interpreter.d.ts +4 -0
  35. package/out/runtime/interpreter.d.ts.map +1 -1
  36. package/out/runtime/interpreter.js +20 -4
  37. package/out/runtime/interpreter.js.map +1 -1
  38. package/out/runtime/loader.d.ts.map +1 -1
  39. package/out/runtime/loader.js +43 -6
  40. package/out/runtime/loader.js.map +1 -1
  41. package/out/runtime/module.d.ts +18 -3
  42. package/out/runtime/module.d.ts.map +1 -1
  43. package/out/runtime/module.js +62 -4
  44. package/out/runtime/module.js.map +1 -1
  45. package/out/runtime/modules/ai.d.ts +18 -2
  46. package/out/runtime/modules/ai.d.ts.map +1 -1
  47. package/out/runtime/modules/ai.js +271 -21
  48. package/out/runtime/modules/ai.js.map +1 -1
  49. package/out/runtime/modules/auth.d.ts.map +1 -1
  50. package/out/runtime/modules/auth.js +11 -5
  51. package/out/runtime/modules/auth.js.map +1 -1
  52. package/out/runtime/resolvers/interface.d.ts +1 -1
  53. package/out/runtime/resolvers/interface.d.ts.map +1 -1
  54. package/out/runtime/resolvers/interface.js.map +1 -1
  55. package/out/runtime/resolvers/sqldb/database.d.ts +1 -0
  56. package/out/runtime/resolvers/sqldb/database.d.ts.map +1 -1
  57. package/out/runtime/resolvers/sqldb/database.js +19 -10
  58. package/out/runtime/resolvers/sqldb/database.js.map +1 -1
  59. package/out/runtime/resolvers/sqldb/impl.d.ts +1 -1
  60. package/out/runtime/resolvers/sqldb/impl.d.ts.map +1 -1
  61. package/out/runtime/resolvers/sqldb/impl.js +2 -2
  62. package/out/runtime/resolvers/sqldb/impl.js.map +1 -1
  63. package/out/runtime/state.d.ts +37 -367
  64. package/out/runtime/state.d.ts.map +1 -1
  65. package/out/runtime/state.js +3 -0
  66. package/out/runtime/state.js.map +1 -1
  67. package/out/setupClassic.d.ts +98 -0
  68. package/out/setupClassic.d.ts.map +1 -0
  69. package/out/setupClassic.js +38 -0
  70. package/out/setupClassic.js.map +1 -0
  71. package/out/setupCommon.d.ts +2 -0
  72. package/out/setupCommon.d.ts.map +1 -0
  73. package/out/setupCommon.js +33 -0
  74. package/out/setupCommon.js.map +1 -0
  75. package/out/setupExtended.d.ts +40 -0
  76. package/out/setupExtended.d.ts.map +1 -0
  77. package/out/setupExtended.js +67 -0
  78. package/out/setupExtended.js.map +1 -0
  79. package/out/syntaxes/agentlang.monarch.js +4 -4
  80. package/out/syntaxes/agentlang.monarch.js.map +1 -1
  81. package/out/utils/runtime.d.ts +7 -6
  82. package/out/utils/runtime.d.ts.map +1 -1
  83. package/package.json +185 -187
  84. package/src/api/http.ts +8 -2
  85. package/src/language/agentlang.langium +8 -2
  86. package/src/language/generated/ast.ts +2204 -1322
  87. package/src/language/generated/grammar.ts +649 -762
  88. package/src/language/generated/module.ts +1 -1
  89. package/src/language/parser.ts +8 -8
  90. package/src/runtime/agents/common.ts +107 -0
  91. package/src/runtime/agents/impl/anthropic.ts +4 -4
  92. package/src/runtime/agents/impl/openai.ts +4 -4
  93. package/src/runtime/auth/defs.ts +1 -1
  94. package/src/runtime/defs.ts +1 -1
  95. package/src/runtime/exec-graph.ts +4 -0
  96. package/src/runtime/interpreter.ts +23 -4
  97. package/src/runtime/loader.ts +43 -4
  98. package/src/runtime/module.ts +80 -3
  99. package/src/runtime/modules/ai.ts +391 -19
  100. package/src/runtime/modules/auth.ts +11 -5
  101. package/src/runtime/resolvers/interface.ts +1 -1
  102. package/src/runtime/resolvers/sqldb/database.ts +20 -11
  103. package/src/runtime/resolvers/sqldb/impl.ts +3 -3
  104. package/src/runtime/state.ts +4 -0
  105. package/src/syntaxes/agentlang.monarch.ts +4 -4
@@ -1,5 +1,5 @@
1
1
  /******************************************************************************
2
- * This file was generated by langium-cli 3.5.2.
2
+ * This file was generated by langium-cli 4.1.0.
3
3
  * DO NOT EDIT MANUALLY!
4
4
  ******************************************************************************/
5
5
 
@@ -411,27 +411,27 @@ function asFnCallPattern(fnCall: FnCall): FunctionCallPattern {
411
411
  }
412
412
 
413
413
  function introspectLiteral(lit: Literal): BasePattern {
414
- if (lit.id) {
414
+ if (lit.id !== undefined) {
415
415
  return LiteralPattern.Id(lit.id);
416
- } else if (lit.num) {
416
+ } else if (lit.num !== undefined) {
417
417
  return LiteralPattern.Number(lit.num);
418
- } else if (lit.ref) {
418
+ } else if (lit.ref !== undefined) {
419
419
  return LiteralPattern.Reference(lit.ref);
420
420
  } else if (lit.str !== undefined) {
421
421
  return LiteralPattern.String(lit.str);
422
- } else if (lit.bool) {
422
+ } else if (lit.bool !== undefined) {
423
423
  return LiteralPattern.Boolean(lit.bool == 'true' ? true : false);
424
- } else if (lit.fnCall) {
424
+ } else if (lit.fnCall !== undefined) {
425
425
  return asFnCallPattern(lit.fnCall);
426
- } else if (lit.asyncFnCall) {
426
+ } else if (lit.asyncFnCall !== undefined) {
427
427
  return asFnCallPattern(lit.asyncFnCall.fnCall).asAsync();
428
- } else if (lit.array) {
428
+ } else if (lit.array !== undefined) {
429
429
  return LiteralPattern.Array(
430
430
  lit.array.vals.map((stmt: Statement) => {
431
431
  return introspectStatement(stmt);
432
432
  })
433
433
  );
434
- } else if (lit.map) {
434
+ } else if (lit.map !== undefined) {
435
435
  return introspectMapLiteral(lit.map);
436
436
  } else {
437
437
  throw new Error(`Invalid literal - ${lit}`);
@@ -167,6 +167,9 @@ The following usage is NOT valid:
167
167
 
168
168
  <pattern> if (<expr>)
169
169
 
170
+ Also C-style ternary-expressions of the form \`condition ? consequent : alternative\` IS INVALID in Agentlang. Always use a proper
171
+ \`if-else\` statement.
172
+
170
173
  A pattern may execute asynchronously and its eventual result can be handled by patterns provided in the '@then' clause. An example is shown below:
171
174
 
172
175
  {sendChatMessage {to "amy", "text" "hello"}} @as response @then {
@@ -362,6 +365,105 @@ case or cases you selected and no additional text or comments. If you decide to
362
365
  Also select the case that is the best match for the given context, no need to look for a perfect match for all values specified in the context.
363
366
  Now apply the same analysis to the following context and cases provided by the user.
364
367
  `;
368
+ export const EvalInstructions = `Consider the following request passed to an intelligent agent and its response. Rate the response on a scale of
369
+ 1-5, where 1 being the lowest score (response unacceptable) and 5 being the highest score (best response). Also describe why you gave a particular score.
370
+ Reply in the JSON format {score: <score-for-the-response, summary: <your-reasons-for-giving-the-score>}`;
371
+
372
+ export const LearningAgentInstructions = `Summarize requirements and use-cases as three constructs: 'decisions' and 'glossaries'.
373
+ Your response must be encoded in JSON. The exact schema will be described later, but let's first consider an example that will help clarify
374
+ how decisions and glossaries could be generate from a use-case. This use-case is from the insurance industry:
375
+
376
+ In insurance, a claim is a formal request made by a policyholder (or beneficiary) to an insurance company asking for financial
377
+ compensation or service because a covered event (loss) has occurred. When the company receives a claim, look at its risk-factor and
378
+ set its approval-mode accordingly. If the risk-factor is 'low', then set the approval-mode to 'auto', if it's 'medium' then set approval-mode to
379
+ 'manual'. If the risk-factor is 'high', then set approval-mode to 'investigate'.
380
+
381
+ Given the above use-case you should return the summary as:
382
+ {
383
+ "summary": "A claim is a request for insurance benefits after a covered loss, and its risk level determines
384
+ whether it is auto-approved, manually reviewed, or investigated.",
385
+ "glossary": [
386
+ {
387
+ "word": "claim",
388
+ "meaning": "A claim is a request to an insurer for payment or service after a covered loss."
389
+ }
390
+ ],
391
+ "decisions": [
392
+ {
393
+ "name": "setApprovalByRiskFactor",
394
+ "conditions": [
395
+ {
396
+ "if": "risk-factor is low",
397
+ "then": "auto"
398
+ },
399
+ {
400
+ "if": "risk-factor is medium",
401
+ "then": "manual"
402
+ },
403
+ {
404
+ "if": "risk-factor is high",
405
+ "then": "investigate"
406
+ }
407
+ ]
408
+ }
409
+ ]
410
+ }
411
+
412
+ Sometimes, the use-case will also contain some examples, which you can summarize as 'scenarios'. An example follows:
413
+
414
+ The ACME company gives salary-hikes to employees based on their sales. If the sales is $50000 or above, a 5-percent hike is given.
415
+ If the sales is between $20000 and $50000, a hike of 2.5% is given. For sales below $20000, no hike is given. An employee who hit
416
+ the target of $50000 is said to have hit a "jackpot". For example, if you see a message that says - "jake@acme.com hit a jackpot", that means
417
+ the employee 'jake@acme.com' is eligible for a 5% hike.
418
+
419
+ Given the above instruction, you should return:
420
+
421
+ {
422
+ "summary": "ACME determines employee salary hikes based on achieved sales figures, with higher sales resulting in higher percentage increases. Employees who meet or exceed the top sales threshold are described as having hit a jackpot.",
423
+ "glossary": [
424
+ {
425
+ "word": "salary-hike",
426
+ "meaning": "An increase in an employee's salary based on defined performance criteria."
427
+ },
428
+ {
429
+ "word": "sales",
430
+ "meaning": "The total revenue generated by an employee, used as the basis for determining salary hikes."
431
+ },
432
+ {
433
+ "word": "jackpot",
434
+ "meaning": "A term used for employees whose sales are 50000 or above, making them eligible for the highest salary hike."
435
+ }
436
+ ],
437
+ "decisions": [
438
+ {
439
+ "name": "determineSalaryHikeBySales",
440
+ "conditions": [
441
+ {
442
+ "if": "sales is 50000 or above",
443
+ "then": "5-percent hike"
444
+ },
445
+ {
446
+ "if": "sales is between 20000 and 50000",
447
+ "then": "2.5-percent hike"
448
+ },
449
+ {
450
+ "if": "sales is below 20000",
451
+ "then": "no hike"
452
+ }
453
+ ]
454
+ }
455
+ ],
456
+ "scenarios": [
457
+ {
458
+ "user": "jake@acme.com hit a jackpot",
459
+ "ai": "give jake@acme.com a hike of 5-percent"
460
+ }
461
+ ]
462
+ }
463
+
464
+ For some user-requests, it may not be able to produce glossary or decisions (or both). In such cases, just return the 'summary'.
465
+ Now process the user-request that follows.
466
+ `;
365
467
 
366
468
  export type AgentCondition = {
367
469
  if: string;
@@ -575,3 +677,8 @@ export function getAgentScratchNames(agentFqName: string): Set<string> | undefin
575
677
  export function removeAgentScratchNames(agentFqName: string) {
576
678
  AgentScratchNames.delete(agentFqName);
577
679
  }
680
+
681
+ export type AgentSummary = {
682
+ data: string;
683
+ summary: string;
684
+ };
@@ -181,15 +181,15 @@ export class AnthropicProvider implements AgentServiceProvider {
181
181
  if (!config) {
182
182
  return {
183
183
  ...defaultConfig,
184
- apiKey: process.env.ANTHROPIC_API_KEY || getLocalEnv('ANTHROPIC_API_KEY'),
184
+ apiKey: process.env.AGENTLANG_ANTHROPIC_KEY || getLocalEnv('AGENTLANG_ANTHROPIC_KEY'),
185
185
  };
186
186
  }
187
187
 
188
188
  const apiKey =
189
189
  config.get('apiKey') ||
190
190
  config.get('api_key') ||
191
- process.env.ANTHROPIC_API_KEY ||
192
- getLocalEnv('ANTHROPIC_API_KEY');
191
+ process.env.AGENTLANG_ANTHROPIC_KEY ||
192
+ getLocalEnv('AGENTLANG_ANTHROPIC_KEY');
193
193
 
194
194
  return {
195
195
  model: config.get('model') || defaultConfig.model,
@@ -266,7 +266,7 @@ export class AnthropicProvider implements AgentServiceProvider {
266
266
  ): Promise<AIResponse> {
267
267
  if (!this.config.apiKey) {
268
268
  throw new Error(
269
- 'Anthropic API key is required. Set ANTHROPIC_API_KEY environment variable or use setLocalEnv("ANTHROPIC_API_KEY", key) or provide apiKey in config.'
269
+ 'Anthropic API key is required. Set AGENTLANG_ANTHROPIC_KEY environment variable or use setLocalEnv("AGENTLANG_ANTHROPIC_KEY", key) or provide apiKey in config.'
270
270
  );
271
271
  }
272
272
 
@@ -69,15 +69,15 @@ export class OpenAIProvider implements AgentServiceProvider {
69
69
  if (!config) {
70
70
  return {
71
71
  ...defaultConfig,
72
- apiKey: process.env.OPENAI_API_KEY || getLocalEnv('OPENAI_API_KEY'),
72
+ apiKey: process.env.AGENTLANG_OPENAI_KEY || getLocalEnv('AGENTLANG_OPENAI_KEY'),
73
73
  };
74
74
  }
75
75
 
76
76
  const apiKey =
77
77
  config.get('apiKey') ||
78
78
  config.get('api_key') ||
79
- process.env.OPENAI_API_KEY ||
80
- getLocalEnv('OPENAI_API_KEY');
79
+ process.env.AGENTLANG_OPENAI_KEY ||
80
+ getLocalEnv('AGENTLANG_OPENAI_KEY');
81
81
 
82
82
  return {
83
83
  model: config.get('model') || defaultConfig.model,
@@ -105,7 +105,7 @@ export class OpenAIProvider implements AgentServiceProvider {
105
105
  async invoke(messages: BaseMessage[], externalToolSpecs: any[] | undefined): Promise<AIResponse> {
106
106
  if (!this.config.apiKey) {
107
107
  throw new Error(
108
- 'OpenAI API key is required. Set OPENAI_API_KEY environment variable or use setLocalEnv("OPENAI_API_KEY", key) or provide apiKey in config.'
108
+ 'OpenAI API key is required. Set AGENTLANG_OPENAI_KEY environment variable or use setLocalEnv("AGENTLANG_OPENAI_KEY", key) or provide apiKey in config.'
109
109
  );
110
110
  }
111
111
  if (externalToolSpecs) {
@@ -1,7 +1,7 @@
1
1
  import { AppConfig } from '../state.js';
2
2
 
3
3
  // TODO: AdminUserId must be dynamically set based on auth-service-config and a valid admin-login
4
- export const AdminUserId = '00000000-0000-0000-0000-000000000000';
4
+ export const AdminUserId = '12345678-1234-1234-1234-123456789abc';
5
5
 
6
6
  export function isAuthEnabled(): boolean {
7
7
  if (AppConfig?.auth?.enabled == true) {
@@ -457,7 +457,7 @@ export function setInternDynamicModuleFn(f: Function) {
457
457
  InternDynamicModule = f;
458
458
  }
459
459
 
460
- export const DefaultTenantId = '00000000-0000-0000-0000-000000000000';
460
+ export const DefaultTenantId = '12345678-1234-1234-1234-123456789abc';
461
461
 
462
462
  export let getUserTenantId = async function (_: string, env: any): Promise<string> {
463
463
  env;
@@ -468,15 +468,18 @@ export async function executeEventHelper(eventInstance: Instance, env?: Environm
468
468
  isLocalEnv = true;
469
469
  }
470
470
  let g: ExecGraph | undefined;
471
+ let escalatedRole: string | undefined;
471
472
  if (!isAgentEventInstance(eventInstance)) {
472
473
  g = await generateExecutionGraph(fqn);
473
474
  if (!g) {
474
475
  throw new Error(`Failed to generate graph for event ${fqn}`);
475
476
  }
477
+ escalatedRole = getWorkflowForEvent(fqn).getRoleEscalation();
476
478
  }
477
479
  const oldModuleName = env.switchActiveModuleName(eventInstance.moduleName);
478
480
  env.bind(eventInstance.name, eventInstance);
479
481
  env.bind(eventInstance.getFqName(), eventInstance);
482
+ if (escalatedRole) env.setEscalatedRole(escalatedRole);
480
483
  try {
481
484
  if (g) {
482
485
  await executeGraph(g, env);
@@ -498,6 +501,7 @@ export async function executeEventHelper(eventInstance: Instance, env?: Environm
498
501
  }
499
502
  throw err;
500
503
  } finally {
504
+ env.resetEscalatedRole();
501
505
  if (!isLocalEnv) env.switchActiveModuleName(oldModuleName);
502
506
  }
503
507
  }
@@ -86,7 +86,7 @@ import {
86
86
  AgentEntityName,
87
87
  AgentFqName,
88
88
  findAgentByName,
89
- trimGeneratedCode,
89
+ normalizeGeneratedCode,
90
90
  } from './modules/ai.js';
91
91
  import { logger } from './logger.js';
92
92
  import {
@@ -165,6 +165,7 @@ export class Environment extends Instance {
165
165
  private agentMode: 'chat' | 'planner' | undefined = undefined;
166
166
  private agentChatId: string | undefined = undefined;
167
167
  private monitor: Monitor | undefined = undefined;
168
+ private escalatedRole: string | undefined;
168
169
 
169
170
  private activeUserData: any = undefined;
170
171
 
@@ -191,6 +192,7 @@ export class Environment extends Instance {
191
192
  this.eventExecutor = parent.eventExecutor;
192
193
  this.agentChatId = parent.agentChatId;
193
194
  this.monitor = parent.monitor;
195
+ this.escalatedRole = parent.escalatedRole;
194
196
  } else {
195
197
  this.activeModule = DefaultModuleName;
196
198
  this.activeResolvers = new Map<string, Resolver>();
@@ -287,6 +289,20 @@ export class Environment extends Instance {
287
289
  return this;
288
290
  }
289
291
 
292
+ setEscalatedRole(s: string): Environment {
293
+ this.escalatedRole = s;
294
+ return this;
295
+ }
296
+
297
+ getEscalatedRole(): string | undefined {
298
+ return this.escalatedRole;
299
+ }
300
+
301
+ resetEscalatedRole(): Environment {
302
+ this.escalatedRole = undefined;
303
+ return this;
304
+ }
305
+
290
306
  private static FlowContextTag = 'flow-context';
291
307
 
292
308
  setFlowContext(s: string): Environment {
@@ -900,6 +916,8 @@ export let evaluate = async function (
900
916
  if (!isEmptyWorkflow(wf)) {
901
917
  env = new Environment(eventInstance.name + '.env', activeEnv);
902
918
  env.setActiveEvent(eventInstance);
919
+ const er = wf.getRoleEscalation();
920
+ if (er) env.setEscalatedRole(er);
903
921
  if (kernelCall) {
904
922
  env.setInKernelMode(true);
905
923
  }
@@ -934,6 +952,7 @@ export let evaluate = async function (
934
952
  throw err;
935
953
  }
936
954
  } finally {
955
+ env?.resetEscalatedRole();
937
956
  if (!txnRolledBack && env !== undefined && activeEnv === undefined) {
938
957
  await env.commitAllTransactions();
939
958
  }
@@ -1959,7 +1978,7 @@ async function agentInvoke(agent: AgentInstance, msg: string, env: Environment):
1959
1978
  let retries = 0;
1960
1979
  while (true) {
1961
1980
  try {
1962
- let rs: string = result ? trimGeneratedCode(result) : '';
1981
+ let rs: string = result ? normalizeGeneratedCode(result) : '';
1963
1982
  let isWf = rs.startsWith('workflow');
1964
1983
  if (isWf && !agent.runWorkflows) {
1965
1984
  await parseWorkflow(rs);
@@ -2013,7 +2032,7 @@ async function agentInvoke(agent: AgentInstance, msg: string, env: Environment):
2013
2032
  let retries = 0;
2014
2033
  while (true) {
2015
2034
  try {
2016
- result = trimGeneratedCode(result);
2035
+ result = normalizeGeneratedCode(result);
2017
2036
  const obj = agent.maybeValidateJsonResponse(result);
2018
2037
  if (obj !== undefined) {
2019
2038
  env.setLastResult(obj);
@@ -2219,7 +2238,7 @@ async function preprocessStep(
2219
2238
  env: Environment
2220
2239
  ): Promise<PreprocStepResult> {
2221
2240
  let needAgentProcessing = true;
2222
- spec = trimGeneratedCode(spec);
2241
+ spec = normalizeGeneratedCode(spec);
2223
2242
  if (spec.startsWith('{') || spec.indexOf(' ') > 0) {
2224
2243
  const newEnv = Environment.from(env, env.name + '_flow_eval', false, true).setActiveModuleName(
2225
2244
  activeModuleName
@@ -1,4 +1,3 @@
1
- import chalk from 'chalk';
2
1
  import { createAgentlangServices } from '../language/agentlang-module.js';
3
2
  import {
4
3
  Import,
@@ -48,6 +47,8 @@ import {
48
47
  RetryDefinition,
49
48
  SetAttribute,
50
49
  CrudMap,
50
+ isAgentEvaluatorDefinition,
51
+ AgentEvaluatorDefinition,
51
52
  } from '../language/generated/ast.js';
52
53
  import {
53
54
  addEntity,
@@ -70,6 +71,7 @@ import {
70
71
  fetchModule,
71
72
  Retry,
72
73
  addGlobalRetry,
74
+ AgentEvaluator,
73
75
  } from './module.js';
74
76
  import {
75
77
  asStringLiteralsMap,
@@ -102,7 +104,13 @@ import {
102
104
  import { logger } from './logger.js';
103
105
  import { Environment, evaluateStatements, GlobalEnvironment } from './interpreter.js';
104
106
  import { createPermission, createRole } from './modules/auth.js';
105
- import { AgentEntityName, CoreAIModuleName, LlmEntityName } from './modules/ai.js';
107
+ import {
108
+ AgentEntityName,
109
+ AgentInstance,
110
+ AgentLearnerType,
111
+ CoreAIModuleName,
112
+ LlmEntityName,
113
+ } from './modules/ai.js';
106
114
  import { getDefaultLLMService } from './agents/registry.js';
107
115
  import { GenericResolver, GenericResolverMethods } from './resolvers/interface.js';
108
116
  import { registerResolver, setResolver } from './resolvers/registry.js';
@@ -125,6 +133,7 @@ import {
125
133
  registerAgentScenarios,
126
134
  registerAgentScratchNames,
127
135
  } from './agents/common.js';
136
+ import chalk from 'chalk';
128
137
 
129
138
  export async function extractDocument(
130
139
  fileName: string,
@@ -418,7 +427,7 @@ export async function loadAppConfig(configDirOrContent: string): Promise<Config>
418
427
  } catch (err: any) {
419
428
  if (err instanceof z.ZodError) {
420
429
  console.log(chalk.red('Config validation failed:'));
421
- err.errors.forEach((error: any, index: number) => {
430
+ err.issues.forEach((error: any, index: number) => {
422
431
  console.log(chalk.red(` ${index + 1}. ${error.path.join('.')}: ${error.message}`));
423
432
  });
424
433
  } else {
@@ -584,7 +593,7 @@ export function addWorkflowFromDef(
584
593
  moduleName: string,
585
594
  ispub: boolean = false
586
595
  ): Workflow {
587
- return addWorkflow(def.name || '', moduleName, def.statements, def.header, ispub);
596
+ return addWorkflow(def.name || '', moduleName, def.statements, def.header, def.directives, ispub);
588
597
  }
589
598
 
590
599
  const StandaloneStatements = new Map<string, Statement[]>();
@@ -842,6 +851,12 @@ async function addAgentDefinition(
842
851
  const service = getDefaultLLMService();
843
852
  wf = `{${CoreAIModuleName}/${LlmEntityName} {name "${llmName}", service "${service}"}, @upsert}; ${wf}`;
844
853
  }
854
+ if (attrs.get('type') === 'planner' || attrs.get('tools')) {
855
+ const llmn = llmName || attrs.get('llm');
856
+ wf = `${wf}; {${CoreAIModuleName}/${AgentEntityName}
857
+ {name "${name}_${AgentLearnerType}", moduleName "${moduleName}", llm "${llmn}",
858
+ type "${AgentLearnerType}", role "You are an agent that summarizes user-provided scenarios."}, @upsert}`;
859
+ }
845
860
  (await parseWorkflow(`workflow A {${wf}}`)).statements.forEach((stmt: Statement) => {
846
861
  addStandaloneStatement(stmt, moduleName, false);
847
862
  });
@@ -1090,6 +1105,29 @@ function addRetryDefinition(def: RetryDefinition, moduleName: string) {
1090
1105
  fetchModule(moduleName).addRetry(retry);
1091
1106
  }
1092
1107
 
1108
+ function addAgentEvaluatorDefinition(def: AgentEvaluatorDefinition, moduleName: string) {
1109
+ if (!def.name) throw new Error('Evaluator definition must have a name');
1110
+ const e = new AgentEvaluator(def.name, moduleName);
1111
+ def.attributes.forEach((sa: SetAttribute) => {
1112
+ const isins = sa.name === 'instruction';
1113
+ if (isins || sa.name === 'llm') {
1114
+ if (isLiteral(sa.value)) {
1115
+ const s = sa.value.id || sa.value.str;
1116
+ if (s) {
1117
+ if (isins) e.setInstruction(s);
1118
+ else e.setLlm(s);
1119
+ } else throw new Error(`Invalid value for evaluator-${sa.name} in ${def.name}`);
1120
+ } else {
1121
+ throw new Error(`evaluator ${sa.name} must be a string in ${def.name}`);
1122
+ }
1123
+ } else {
1124
+ throw new Error(`invalid attribute ${sa.name} in evaluator ${def.name}`);
1125
+ }
1126
+ });
1127
+ fetchModule(moduleName).addAgentEvaluator(e);
1128
+ AgentInstance.RegisterEvaluator(e);
1129
+ }
1130
+
1093
1131
  function addResolverDefinition(def: ResolverDefinition, moduleName: string) {
1094
1132
  const resolverName = `${moduleName}/${def.name}`;
1095
1133
  const paths = def.paths;
@@ -1157,6 +1195,7 @@ export async function addFromDef(def: Definition, moduleName: string) {
1157
1195
  else if (isDirectiveDefinition(def)) addDirectiveDefintion(def, moduleName);
1158
1196
  else if (isGlossaryEntryDefinition(def)) addGlossaryEntryDefintion(def, moduleName);
1159
1197
  else if (isRetryDefinition(def)) addRetryDefinition(def, moduleName);
1198
+ else if (isAgentEvaluatorDefinition(def)) addAgentEvaluatorDefinition(def, moduleName);
1160
1199
  }
1161
1200
 
1162
1201
  export async function parseAndIntern(code: string, moduleName?: string) {
@@ -22,6 +22,7 @@ import {
22
22
  WorkflowHeader,
23
23
  FlowDefinition,
24
24
  FlowEntry,
25
+ WorkflowDirectives,
25
26
  } from '../language/generated/ast.js';
26
27
  import {
27
28
  Path,
@@ -1517,11 +1518,19 @@ export class Relationship extends Record {
1517
1518
  export class Workflow extends ModuleEntry {
1518
1519
  statements: Statement[];
1519
1520
  isPrePost: boolean;
1521
+ directives: WorkflowDirectives | undefined;
1520
1522
 
1521
- constructor(name: string, patterns: Statement[], moduleName: string, isPrePost: boolean = false) {
1523
+ constructor(
1524
+ name: string,
1525
+ patterns: Statement[],
1526
+ moduleName: string,
1527
+ isPrePost: boolean = false,
1528
+ directives?: WorkflowDirectives
1529
+ ) {
1522
1530
  super(name, moduleName);
1523
1531
  this.statements = patterns;
1524
1532
  this.isPrePost = isPrePost;
1533
+ this.directives = directives;
1525
1534
  }
1526
1535
 
1527
1536
  async addStatement(stmtCode: string): Promise<Workflow> {
@@ -1648,10 +1657,29 @@ export class Workflow extends ModuleEntry {
1648
1657
  return this;
1649
1658
  }
1650
1659
 
1660
+ getRoleEscalation(): string | undefined {
1661
+ if (this.directives !== undefined) {
1662
+ for (let i = 0; i < this.directives.entries.length; ++i) {
1663
+ const e = this.directives.entries[i];
1664
+ if (e.tag === '@withRole') {
1665
+ return e.value;
1666
+ }
1667
+ }
1668
+ }
1669
+ return undefined;
1670
+ }
1671
+
1672
+ private directivesToString(): string {
1673
+ if (this.directives !== undefined) {
1674
+ return ` ${this.directives.$cstNode?.text || ''} `;
1675
+ }
1676
+ return ' ';
1677
+ }
1678
+
1651
1679
  override toString() {
1652
1680
  const n = this.isPrePost ? untangleWorkflowName(this.name) : this.name;
1653
1681
  const nn = normalizeWorkflowName(n);
1654
- let s: string = `workflow ${nn} {\n`;
1682
+ let s: string = `workflow ${nn}${this.directivesToString()}{\n`;
1655
1683
  const ss = this.statementsToStringsHelper(this.statements);
1656
1684
  s = s.concat(joinStatements(ss));
1657
1685
  if (!this.isPrePost) {
@@ -2091,6 +2119,49 @@ export class Retry extends ModuleEntry {
2091
2119
  }
2092
2120
  }
2093
2121
 
2122
+ export class AgentEvaluator extends ModuleEntry {
2123
+ instruction: string | undefined;
2124
+ llm: string | undefined;
2125
+
2126
+ constructor(name: string, moduleName: string) {
2127
+ super(name, moduleName);
2128
+ }
2129
+
2130
+ setInstruction(ins: string): AgentEvaluator {
2131
+ this.instruction = ins;
2132
+ return this;
2133
+ }
2134
+
2135
+ setLlm(llm: string): AgentEvaluator {
2136
+ this.llm = llm;
2137
+ return this;
2138
+ }
2139
+
2140
+ private static suffix = '_eval';
2141
+
2142
+ escapeName(): AgentEvaluator {
2143
+ this.name = `${this.name}${AgentEvaluator.suffix}`;
2144
+ return this;
2145
+ }
2146
+
2147
+ normalizedName(): string {
2148
+ const i = this.name.lastIndexOf(AgentEvaluator.suffix);
2149
+ if (i >= 0) {
2150
+ return this.name.substring(0, i);
2151
+ }
2152
+ return this.name;
2153
+ }
2154
+
2155
+ override toString(): string {
2156
+ let s = '';
2157
+ if (this.instruction) s = ` instruction "${this.instruction}"`;
2158
+ if (this.llm) s = `${s}\n llm "${this.llm}"`;
2159
+ return `evaluator ${this.normalizedName()} {
2160
+ ${s}
2161
+ }`;
2162
+ }
2163
+ }
2164
+
2094
2165
  export class Decision extends ModuleEntry {
2095
2166
  cases: string[];
2096
2167
 
@@ -2395,6 +2466,11 @@ export class Module {
2395
2466
  return this;
2396
2467
  }
2397
2468
 
2469
+ addAgentEvaluator(e: AgentEvaluator): Module {
2470
+ this.addEntry(e.escapeName());
2471
+ return this;
2472
+ }
2473
+
2398
2474
  getRetry(name: string): Retry | undefined {
2399
2475
  if (this.hasEntry(name)) {
2400
2476
  const e = this.getEntry(name);
@@ -3092,6 +3168,7 @@ export function addWorkflow(
3092
3168
  moduleName = activeModule,
3093
3169
  statements?: Statement[],
3094
3170
  hdr?: WorkflowHeader | ThinWfHeader,
3171
+ directives?: WorkflowDirectives,
3095
3172
  ispub: boolean = false
3096
3173
  ): Workflow {
3097
3174
  if (hdr) {
@@ -3130,7 +3207,7 @@ export function addWorkflow(
3130
3207
  });
3131
3208
  }
3132
3209
  return module.addEntry(
3133
- new Workflow(asWorkflowName(name), statements, moduleName, hdr ? true : false)
3210
+ new Workflow(asWorkflowName(name), statements, moduleName, hdr ? true : false, directives)
3134
3211
  ) as Workflow;
3135
3212
  }
3136
3213