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
@@ -5,6 +5,7 @@ import {
5
5
  makeCoreModuleName,
6
6
  makeFqName,
7
7
  nameToPath,
8
+ restoreSpecialChars,
8
9
  sleepMilliseconds,
9
10
  splitFqName,
10
11
  } from '../util.js';
@@ -15,6 +16,7 @@ import {
15
16
  parseAndEvaluateStatement,
16
17
  } from '../interpreter.js';
17
18
  import {
19
+ AgentEvaluator,
18
20
  asJSONSchema,
19
21
  Decision,
20
22
  fetchModule,
@@ -38,18 +40,21 @@ import {
38
40
  humanMessage,
39
41
  systemMessage,
40
42
  } from '../agents/provider.js';
41
- import { AIMessage, BaseMessage, HumanMessage } from '@langchain/core/messages';
43
+ import { AIMessage, BaseMessage, HumanMessage, SystemMessage } from '@langchain/core/messages';
42
44
  import {
43
45
  AgentCondition,
44
46
  AgentGlossaryEntry,
45
47
  AgentScenario,
48
+ AgentSummary as AgentLearningResult,
46
49
  DecisionAgentInstructions,
50
+ EvalInstructions,
47
51
  FlowExecInstructions,
48
52
  getAgentDirectives,
49
53
  getAgentGlossary,
50
54
  getAgentResponseSchema,
51
55
  getAgentScenarios,
52
56
  getAgentScratchNames,
57
+ LearningAgentInstructions as LearnerAgentInstructions,
53
58
  newAgentDirective,
54
59
  newAgentGlossaryEntry,
55
60
  newAgentScenario,
@@ -65,9 +70,14 @@ import { isMonitoringEnabled, TtlCache } from '../state.js';
65
70
  export const CoreAIModuleName = makeCoreModuleName('ai');
66
71
  export const AgentEntityName = 'Agent';
67
72
  export const LlmEntityName = 'LLM';
73
+ export const AgentLearnerType = 'learner';
74
+
75
+ const AgentEvalType = 'eval';
68
76
 
69
77
  export default `module ${CoreAIModuleName}
70
78
 
79
+ import "./modules/ai.js" @as ai
80
+
71
81
  entity ${LlmEntityName} {
72
82
  name String @id,
73
83
  service String @default("openai"),
@@ -77,7 +87,7 @@ entity ${LlmEntityName} {
77
87
  entity ${AgentEntityName} {
78
88
  name String @id,
79
89
  moduleName String @default("${CoreAIModuleName}"),
80
- type @enum("chat", "planner", "flow-exec") @default("chat"),
90
+ type @enum("chat", "planner", "flow-exec", "${AgentEvalType}", "${AgentLearnerType}") @default("chat"),
81
91
  runWorkflows Boolean @default(true),
82
92
  instruction String @optional,
83
93
  tools String @optional, // comma-separated list of tool names
@@ -136,8 +146,122 @@ entity GlossaryEntry {
136
146
  meaning String,
137
147
  synonyms String @optional
138
148
  }
149
+
150
+ entity EvaluationResult {
151
+ id UUID @id @default(uuid()),
152
+ agentFqName String @indexed,
153
+ userRequest String,
154
+ score Int,
155
+ summary String
156
+ }
157
+
158
+ entity AgentLearningResult {
159
+ id UUID @id @default(uuid()),
160
+ agentFqName String @indexed,
161
+ data String,
162
+ summary String
163
+ }
164
+
165
+ @public event agentLearning{
166
+ agentName String,
167
+ agentModuleName String,
168
+ instruction String
169
+ }
170
+
171
+ workflow agentLearning {
172
+ await ai.processAgentLearning(agentLearning.agentModuleName, agentLearning.agentName, agentLearning.instruction)
173
+ }
139
174
  `;
140
175
 
176
+ enum AgentCacheType {
177
+ DIRECTIVE,
178
+ GLOSSARY,
179
+ SCENARIO,
180
+ SUMMARY,
181
+ }
182
+
183
+ type AgentInstructionActivator = {
184
+ provider: AgentServiceProvider;
185
+ userMessage: string;
186
+ agentInstruction: string;
187
+ agentRole: string | undefined;
188
+ };
189
+
190
+ const MAX_USER_DEFINED_GLOSSARY = 20;
191
+ const MAX_USER_DEFINED_DIRECTIVES = 20;
192
+ const MAX_USER_DEFINED_SCENARIOS = 5;
193
+ const MAX_USER_DEFINED_SUMMARIES = 5;
194
+
195
+ async function activatedUserDefinedAgentLearnings<T>(
196
+ objLabel: string,
197
+ learningObjects: T[],
198
+ activator: AgentInstructionActivator,
199
+ maxResults: number
200
+ ): Promise<T[]> {
201
+ const msg = `Consider the following ${objLabel} (in JSON format):
202
+ ${JSON.stringify(learningObjects)}
203
+
204
+ Return the indices of the ${objLabel} relevant for the following text:
205
+
206
+ ${activator.userMessage}
207
+
208
+ Return the relevant indices and a JSON array of integers with the index starting at zero (0). Do not return any additional comments
209
+ or text.
210
+ `;
211
+ const msgs = new Array<BaseMessage>();
212
+ msgs.push(
213
+ new SystemMessage(
214
+ 'You are an agent that filters a JSON array and return relevant indices as a JSON array of integers.'
215
+ )
216
+ );
217
+ msgs.push(new HumanMessage(msg));
218
+ const response: AIResponse = await activator.provider.invoke(msgs, undefined);
219
+ const indices: number[] = JSON.parse(normalizeGeneratedCode(response.content));
220
+ if (indices.length == 0 || indices.length == learningObjects.length) return learningObjects;
221
+ const result = new Array<T>();
222
+ for (let i = 0; i < indices.length; ++i) {
223
+ if (i >= maxResults) break;
224
+ result.push(learningObjects[indices[i]]);
225
+ }
226
+ return result;
227
+ }
228
+
229
+ async function activatedUserDefinedAgentGlossary(
230
+ gls: AgentGlossaryEntry[],
231
+ activator: AgentInstructionActivator
232
+ ): Promise<AgentGlossaryEntry[]> {
233
+ return await activatedUserDefinedAgentLearnings<AgentGlossaryEntry>(
234
+ 'glossary entries',
235
+ gls,
236
+ activator,
237
+ MAX_USER_DEFINED_GLOSSARY
238
+ );
239
+ }
240
+
241
+ async function activatedUserDefinedAgentScenarios(
242
+ scns: AgentScenario[],
243
+ activator: AgentInstructionActivator
244
+ ): Promise<AgentScenario[]> {
245
+ return await activatedUserDefinedAgentLearnings<AgentScenario>(
246
+ 'scenarios',
247
+ scns,
248
+ activator,
249
+ MAX_USER_DEFINED_SCENARIOS
250
+ );
251
+ }
252
+
253
+ async function activatedUserDefinedAgentDirectives(
254
+ dirs: AgentCondition[],
255
+ activator: AgentInstructionActivator
256
+ ): Promise<AgentCondition[]> {
257
+ return await activatedUserDefinedAgentLearnings<AgentCondition>(
258
+ 'directives or conditions',
259
+ dirs,
260
+ activator,
261
+ MAX_USER_DEFINED_DIRECTIVES
262
+ );
263
+ }
264
+
141
265
  export const AgentFqName = makeFqName(CoreAIModuleName, AgentEntityName);
142
266
 
143
267
  const ProviderDb = new Map<string, AgentServiceProvider>();
@@ -276,10 +400,18 @@ export class AgentInstance {
276
400
  return this.hasModuleTools || this.type == 'planner';
277
401
  }
278
402
 
403
+ isLearner(): boolean {
404
+ return this.type === 'learner';
405
+ }
406
+
279
407
  isFlowExecutor(): boolean {
280
408
  return this.type == 'flow-exec';
281
409
  }
282
410
 
411
+ isEvaluator(): boolean {
412
+ return this.type == AgentEvalType;
413
+ }
414
+
283
415
  markAsDecisionExecutor(): AgentInstance {
284
416
  this.decisionExecutor = true;
285
417
  return this;
@@ -301,14 +433,22 @@ export class AgentInstance {
301
433
  let r: AgentCondition[] = [];
302
434
  if (result && result.length > 0) {
303
435
  r = result.map((inst: Instance) => {
304
- return newAgentDirective(inst.lookup('condition'), inst.lookup('consequent'));
436
+ return newAgentDirective(
437
+ restoreSpecialChars(inst.lookup('condition')),
438
+ restoreSpecialChars(inst.lookup('consequent'))
439
+ );
305
440
  });
306
441
  }
307
442
  return AgentInstance.DirectivesCache.set(fqName, r);
308
443
  }
309
444
 
310
- private async directivesAsString(fqName: string): Promise<string> {
311
- const userDirs = await this.getUserDefinedAgentDirectives(fqName);
445
+ private async directivesAsString(
446
+ fqName: string,
447
+ activator: AgentInstructionActivator
448
+ ): Promise<string> {
449
+ let userDirs = await this.getUserDefinedAgentDirectives(fqName);
450
+ if (userDirs.length > MAX_USER_DEFINED_DIRECTIVES)
451
+ userDirs = await activatedUserDefinedAgentDirectives(userDirs, activator);
312
452
  const dirs = getAgentDirectives(fqName) || [];
313
453
  const conds = dirs.concat(userDirs);
314
454
  if (conds.length > 0) {
@@ -341,7 +481,7 @@ export class AgentInstance {
341
481
  r = result.map((inst: Instance) => {
342
482
  return newAgentGlossaryEntry(
343
483
  inst.lookup('name'),
344
- inst.lookup('meaning'),
484
+ restoreSpecialChars(inst.lookup('meaning')),
345
485
  inst.lookup('synonyms')
346
486
  );
347
487
  });
@@ -349,6 +489,23 @@ export class AgentInstance {
349
489
  return AgentInstance.GlossaryCache.set(fqName, r);
350
490
  }
351
491
 
492
+ private static SummariesCache = new TtlCache<AgentLearningResult[]>(AgentInstance.CACHE_TTL_MS);
493
+
494
+ private async getUserDefinedAgentLearningResults(fqName: string): Promise<AgentLearningResult[]> {
495
+ const cached = AgentInstance.SummariesCache.get(fqName);
496
+ if (cached !== undefined) return cached;
497
+ const result: Instance[] = await parseAndEvaluateStatement(
498
+ `{${CoreAIModuleName}/AgentLearningResult {agentFqName? "${fqName}"}}`
499
+ );
500
+ let r: AgentLearningResult[] = [];
501
+ if (result && result.length > 0) {
502
+ r = result.map((inst: Instance) => {
503
+ return { data: inst.lookup('data'), summary: inst.lookup('summary') };
504
+ });
505
+ }
506
+ return AgentInstance.SummariesCache.set(fqName, r);
507
+ }
508
+
352
509
  private static ScenariosCache = new TtlCache<AgentScenario[]>(AgentInstance.CACHE_TTL_MS);
353
510
 
354
511
  private async getUserDefinedAgentScenarios(fqName: string): Promise<AgentScenario[]> {
@@ -366,12 +523,34 @@ export class AgentInstance {
366
523
  return AgentInstance.ScenariosCache.set(fqName, r);
367
524
  }
368
525
 
369
- private async getFullInstructions(env: Environment): Promise<string> {
526
+ public static ResetCache(fqName: string, type: AgentCacheType) {
527
+ switch (type) {
528
+ case AgentCacheType.DIRECTIVE:
529
+ AgentInstance.DirectivesCache.delete(fqName);
530
+ break;
531
+ case AgentCacheType.GLOSSARY:
532
+ AgentInstance.GlossaryCache.delete(fqName);
533
+ break;
534
+ case AgentCacheType.SCENARIO:
535
+ AgentInstance.ScenariosCache.delete(fqName);
536
+ break;
537
+ case AgentCacheType.SUMMARY:
538
+ AgentInstance.SummariesCache.delete(fqName);
539
+ break;
540
+ }
541
+ }
542
+
543
+ private async getFullInstructions(
544
+ env: Environment,
545
+ activator: AgentInstructionActivator
546
+ ): Promise<string> {
370
547
  const fqName = this.getFqName();
371
548
  const ins = this.role ? `${this.role}\n${this.instruction || ''}` : this.instruction || '';
372
- let finalInstruction = `${ins} ${await this.directivesAsString(fqName)}`;
549
+ let finalInstruction = `${ins} ${await this.directivesAsString(fqName, activator)}`;
373
550
  const staticGls = getAgentGlossary(fqName) || [];
374
- const userGls = await this.getUserDefinedAgentGlossary(fqName);
551
+ let userGls = await this.getUserDefinedAgentGlossary(fqName);
552
+ if (userGls.length > MAX_USER_DEFINED_GLOSSARY)
553
+ userGls = await activatedUserDefinedAgentGlossary(userGls, activator);
375
554
  const gls = staticGls.concat(userGls);
376
555
  if (gls.length > 0) {
377
556
  const glss = new Array<string>();
@@ -384,7 +563,9 @@ export class AgentInstance {
384
563
  ${glss.join('\n')}\n`;
385
564
  }
386
565
  const staticScns = getAgentScenarios(fqName) || [];
387
- const userScns = await this.getUserDefinedAgentScenarios(fqName);
566
+ let userScns = await this.getUserDefinedAgentScenarios(fqName);
567
+ if (userScns.length > MAX_USER_DEFINED_SCENARIOS)
568
+ userScns = await activatedUserDefinedAgentScenarios(userScns, activator);
388
569
  const scenarios = staticScns.concat(userScns);
389
570
  if (scenarios.length > 0) {
390
571
  const scs = new Array<string>();
@@ -398,6 +579,20 @@ export class AgentInstance {
398
579
  });
399
580
  finalInstruction = `${finalInstruction}\nHere are some example user requests and the corresponding responses you are supposed to produce:\n${scs.join('\n')}`;
400
581
  }
582
+ const summaries = await this.getUserDefinedAgentLearningResults(fqName);
583
+ if (summaries.length > 0) {
584
+ let s: string[] = summaries.map((sa: AgentLearningResult) => {
585
+ return restoreSpecialChars(sa.summary);
586
+ });
587
+ if (s.length > MAX_USER_DEFINED_SUMMARIES)
588
+ s = await activatedUserDefinedAgentLearnings<string>(
589
+ 'summaries',
590
+ s,
591
+ activator,
592
+ MAX_USER_DEFINED_SUMMARIES
593
+ );
594
+ finalInstruction = `${finalInstruction}\nAlso keep in mind the following points:\n\n${s.join('\n')}\n\n`;
595
+ }
401
596
  const responseSchema = getAgentResponseSchema(fqName);
402
597
  if (responseSchema) {
403
598
  finalInstruction = `${finalInstruction}\nReturn your response in the following JSON schema:\n${asJSONSchema(responseSchema)}
@@ -430,7 +625,7 @@ Only return a pure JSON object with no extra text, annotations etc.`;
430
625
  if (response) {
431
626
  const responseSchema = getAgentResponseSchema(this.getFqName());
432
627
  if (responseSchema) {
433
- const attrs = JSON.parse(trimGeneratedCode(response));
628
+ const attrs = JSON.parse(normalizeGeneratedCode(response));
434
629
  const parts = nameToPath(responseSchema);
435
630
  const moduleName = parts.getModuleName();
436
631
  const entryName = parts.getEntryName();
@@ -495,16 +690,78 @@ Only return a pure JSON object with no extra text, annotations etc.`;
495
690
  return this;
496
691
  }
497
692
 
693
+ private static AgentEvaluators = new Map<string, AgentInstance>();
694
+
695
+ public static RegisterEvaluator(e: AgentEvaluator): AgentInstance {
696
+ const n = e.normalizedName();
697
+ const agentFqName = isFqName(n) ? n : makeFqName(e.moduleName, n);
698
+ const instruction = e.instruction;
699
+ let llm = e.llm;
700
+ const [agentModule, agentName] = splitFqName(agentFqName);
701
+ if (llm === undefined) llm = `${agentName}_llm`;
702
+ const inst = makeInstance(
703
+ CoreAIModuleName,
704
+ AgentEntityName,
705
+ newInstanceAttributes()
706
+ .set('llm', llm)
707
+ .set('name', agentName)
708
+ .set('moduleName', agentModule)
709
+ .set(
710
+ 'instruction',
711
+ instruction || 'You are an agent that evaluates the performance of another agent.'
712
+ )
713
+ .set('type', AgentEvalType)
714
+ );
715
+ const einst = AgentInstance.FromInstance(inst).disableSession();
716
+ this.AgentEvaluators.set(agentFqName, einst);
717
+ return einst;
718
+ }
719
+
720
+ private static async maybeEvaluateResponse(
721
+ agent: AgentInstance,
722
+ userRequest: string,
723
+ fullRequest: string,
724
+ response: string,
725
+ env: Environment
726
+ ): Promise<void> {
727
+ const fqn = agent.getFqName();
728
+ const e: AgentInstance | undefined = AgentInstance.AgentEvaluators.get(fqn);
729
+ if (e !== undefined) {
730
+ await e.invoke(
731
+ JSON.stringify({ requestToAgent: fullRequest, responseFromAgent: response }),
732
+ env
733
+ );
734
+ try {
735
+ const r = JSON.parse(normalizeGeneratedCode(env.getLastResult()));
736
+ const score = r.score;
737
+ if (score === undefined || score === null) {
738
+ logger.warn(`Evaluation for agent ${fqn} failed to generate a valid score`);
739
+ } else {
740
+ await parseAndEvaluateStatement(`{${CoreAIModuleName}/EvaluationResult {
741
+ agentFqName "${fqn}",
742
+ userRequest "${escapeSpecialChars(userRequest)}",
743
+ score ${score},
744
+ summary "${escapeSpecialChars(r.summary)}"
745
+ }}`);
746
+ }
747
+ } catch (reason: any) {
748
+ logger.warn(`Failed to save evaluation for agent ${fqn} - ${reason}`);
749
+ }
750
+ }
751
+ }
752
+
498
753
  async invoke(message: string, env: Environment) {
499
754
  const p = await findProviderForLLM(this.llm, env);
500
755
  const agentName = this.name;
501
756
  const chatId = env.getAgentChatId() || agentName;
502
757
  let isplnr = this.isPlanner();
503
758
  const isflow = !isplnr && this.isFlowExecutor();
504
- if (isplnr && this.withSession) {
759
+ const iseval = !isplnr && !isflow && this.isEvaluator();
760
+ const islearner = !isflow && !isplnr && !iseval && this.isLearner();
761
+ if ((isplnr || islearner || iseval) && this.withSession) {
505
762
  this.withSession = false;
506
763
  }
507
- if (isflow) {
764
+ if (isflow || islearner) {
508
765
  this.withSession = false;
509
766
  }
510
767
  if (this.withSession && env.getFlowContext()) {
@@ -520,19 +777,31 @@ Only return a pure JSON object with no extra text, annotations etc.`;
520
777
  const sess: Instance | null = this.withSession ? await findAgentChatSession(chatId, env) : null;
521
778
  let msgs: BaseMessage[] | undefined;
522
779
  let cachedMsg: string | undefined = undefined;
780
+ const activator: AgentInstructionActivator = {
781
+ provider: p,
782
+ userMessage: message,
783
+ agentInstruction: this.instruction,
784
+ agentRole: this.role,
785
+ };
523
786
  if (sess) {
524
787
  msgs = sess.lookup('messages');
525
788
  } else {
526
- cachedMsg = await this.getFullInstructions(env);
789
+ cachedMsg = await this.getFullInstructions(env, activator);
527
790
  msgs = [systemMessage(cachedMsg || '')];
528
791
  }
529
792
  if (msgs) {
530
793
  try {
531
794
  const sysMsg = msgs[0];
532
- if (isplnr || isflow) {
533
- const s = isplnr ? PlannerInstructions : FlowExecInstructions;
795
+ if (isplnr || isflow || iseval || islearner) {
796
+ const s = isplnr
797
+ ? PlannerInstructions
798
+ : isflow
799
+ ? FlowExecInstructions
800
+ : iseval
801
+ ? EvalInstructions
802
+ : LearnerAgentInstructions;
534
803
  const ts = this.toolsAsString();
535
- const msg = `${s}\n${ts}\n${cachedMsg || (await this.getFullInstructions(env))}`;
804
+ const msg = `${s}\n${ts}\n${cachedMsg || (await this.getFullInstructions(env, activator))}`;
536
805
  const newSysMsg = systemMessage(msg);
537
806
  msgs[0] = newSysMsg;
538
807
  }
@@ -570,6 +839,14 @@ Only return a pure JSON object with no extra text, annotations etc.`;
570
839
  if (v) {
571
840
  response = await this.handleValidation(response, v, msgs, p);
572
841
  }
842
+ if (!iseval)
843
+ await AgentInstance.maybeEvaluateResponse(
844
+ this,
845
+ message,
846
+ msgsContent,
847
+ response.content,
848
+ env
849
+ );
573
850
  msgs.push(assistantMessage(response.content));
574
851
  if (isplnr) {
575
852
  msgs[0] = sysMsg;
@@ -606,7 +883,7 @@ Only return a pure JSON object with no extra text, annotations etc.`;
606
883
  validationEventName: string
607
884
  ): Promise<Instance> {
608
885
  let isstr = true;
609
- const content = trimGeneratedCode(response.content);
886
+ const content = normalizeGeneratedCode(response.content);
610
887
  try {
611
888
  const c = JSON.parse(content);
612
889
  isstr = isString(c);
@@ -920,7 +1197,7 @@ function processScenarioResponse(resp: string): string {
920
1197
  return resp;
921
1198
  }
922
1199
 
923
- export function trimGeneratedCode(code: string | undefined): string {
1200
+ export function normalizeGeneratedCode(code: string | undefined): string {
924
1201
  if (code !== undefined) {
925
1202
  let s = code.trim();
926
1203
  if (s.startsWith('```')) {
@@ -935,3 +1212,98 @@ export function trimGeneratedCode(code: string | undefined): string {
935
1212
  return '';
936
1213
  }
937
1214
  }
1215
+
1216
+ async function parseAndInternAgentLearning(
1217
+ moduleName: string,
1218
+ agentName: string,
1219
+ learning: string,
1220
+ env: Environment
1221
+ ) {
1222
+ const obj = JSON.parse(normalizeGeneratedCode(learning));
1223
+ const fqName = makeFqName(moduleName, agentName);
1224
+ if (obj.decisions) {
1225
+ for (let j = 0; j < obj.decisions.length; ++j) {
1226
+ const conds: any[] = obj.decisions[j].conditions;
1227
+ if (conds && conds.length > 0) {
1228
+ AgentInstance.ResetCache(fqName, AgentCacheType.DIRECTIVE);
1229
+ for (let i = 0; i < conds.length; ++i) {
1230
+ const entry: any = conds[i];
1231
+ const cond: string = entry.if;
1232
+ const conseq: string = entry.then;
1233
+ if (cond && conseq) {
1234
+ await parseAndEvaluateStatement(
1235
+ `{${CoreAIModuleName}/Directive {
1236
+ agentFqName "${fqName}",
1237
+ condition "${escapeSpecialChars(cond)}",
1238
+ consequent "${escapeSpecialChars(conseq)}"}}`,
1239
+ env.getActiveUser(),
1240
+ env
1241
+ );
1242
+ } else {
1243
+ throw new Error(`Invalid directive generated - missing 'if' or 'then' in ${learning}`);
1244
+ }
1245
+ }
1246
+ }
1247
+ }
1248
+ }
1249
+ if (obj.glossary) {
1250
+ AgentInstance.ResetCache(fqName, AgentCacheType.GLOSSARY);
1251
+ for (let i = 0; i < obj.glossary.length; ++i) {
1252
+ const word = obj.glossary[i].word;
1253
+ const meaning = obj.glossary[i].meaning;
1254
+ if (word && meaning) {
1255
+ await parseAndEvaluateStatement(
1256
+ `{${CoreAIModuleName}/GlossaryEntry {
1257
+ agentFqName "${fqName}",
1258
+ name "${word}",
1259
+ meaning "${escapeSpecialChars(meaning)}"}}`,
1260
+ env.getActiveUser(),
1261
+ env
1262
+ );
1263
+ }
1264
+ }
1265
+ }
1266
+ if (obj.scenarios) {
1267
+ AgentInstance.ResetCache(fqName, AgentCacheType.SCENARIO);
1268
+ for (let i = 0; i < obj.scenarios.length; ++i) {
1269
+ const user = obj.scenarios[i].user;
1270
+ const ai = obj.scenarios[i].ai;
1271
+ if (user && ai) {
1272
+ await parseAndEvaluateStatement(
1273
+ `{${CoreAIModuleName}/Scenario {
1274
+ agentFqName "${fqName}",
1275
+ user "${escapeSpecialChars(user)}",
1276
+ ai "${escapeSpecialChars(ai)}"}}`,
1277
+ env.getActiveUser(),
1278
+ env
1279
+ );
1280
+ }
1281
+ }
1282
+ }
1283
+ AgentInstance.ResetCache(fqName, AgentCacheType.SUMMARY);
1284
+ const summary = obj.summary;
1285
+ delete obj.summary;
1286
+ await parseAndEvaluateStatement(
1287
+ `{${CoreAIModuleName}/AgentLearningResult {
1288
+ agentFqName "${fqName}",
1289
+ data "${escapeSpecialChars(JSON.stringify(obj))}",
1290
+ summary "${escapeSpecialChars(summary) || ''}"}}`,
1291
+ env.getActiveUser(),
1292
+ env
1293
+ );
1294
+ }
1295
+
1296
+ export async function processAgentLearning(
1297
+ moduleName: string,
1298
+ agentName: string,
1299
+ instruction: string,
1300
+ env: Environment
1301
+ ): Promise<any> {
1302
+ const learning = await parseAndEvaluateStatement(
1303
+ `{${moduleName}/${agentName}_${AgentLearnerType} {message \`${instruction}\`}}`,
1304
+ env.getActiveUser(),
1305
+ env
1306
+ );
1307
+ await parseAndInternAgentLearning(moduleName, agentName, learning, env);
1308
+ return { agentLearning: { result: learning } };
1309
+ }
@@ -959,9 +959,15 @@ export async function userHasPermissions(
959
959
  }
960
960
  UserRoleCache.set(userId, userRoles);
961
961
  }
962
+ let tempRoles = userRoles;
963
+ const escalatedRole = env.getEscalatedRole();
964
+ if (escalatedRole) {
965
+ tempRoles = userRoles.slice();
966
+ tempRoles.push(escalatedRole);
967
+ }
962
968
  if (
963
- userRoles &&
964
- userRoles.find((role: string) => {
969
+ tempRoles &&
970
+ tempRoles.find((role: string) => {
965
971
  return role === 'admin';
966
972
  })
967
973
  ) {
@@ -973,9 +979,9 @@ export async function userHasPermissions(
973
979
  perms.has(RbacPermissionFlag.UPDATE),
974
980
  perms.has(RbacPermissionFlag.DELETE),
975
981
  ];
976
- if (userRoles !== null) {
977
- for (let i = 0; i < userRoles.length; ++i) {
978
- const permInsts: RbacPermission[] | undefined = RolePermissionsCache.get(userRoles[i]);
982
+ if (tempRoles !== null) {
983
+ for (let i = 0; i < tempRoles.length; ++i) {
984
+ const permInsts: RbacPermission[] | undefined = RolePermissionsCache.get(tempRoles[i]);
979
985
  if (permInsts) {
980
986
  if (
981
987
  permInsts.find((p: RbacPermission) => {
@@ -174,7 +174,7 @@ export class Resolver {
174
174
  entryName: string,
175
175
  moduleName: string,
176
176
  query: string,
177
- options?: Map<string, any>
177
+ options?: any
178
178
  ): Promise<any> {
179
179
  return this.notImpl(`fullTextSearch(${entryName}, ${moduleName}, ${query}, ${options})`);
180
180
  }