agentlang 0.10.4 → 0.10.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 (111) hide show
  1. package/README.md +22 -9
  2. package/out/extension/main.cjs +250 -250
  3. package/out/extension/main.cjs.map +2 -2
  4. package/out/language/generated/ast.d.ts +2 -12
  5. package/out/language/generated/ast.d.ts.map +1 -1
  6. package/out/language/generated/ast.js +0 -8
  7. package/out/language/generated/ast.js.map +1 -1
  8. package/out/language/generated/grammar.d.ts.map +1 -1
  9. package/out/language/generated/grammar.js +18 -52
  10. package/out/language/generated/grammar.js.map +1 -1
  11. package/out/language/main.cjs +522 -564
  12. package/out/language/main.cjs.map +3 -3
  13. package/out/language/parser.d.ts.map +1 -1
  14. package/out/language/parser.js +10 -3
  15. package/out/language/parser.js.map +1 -1
  16. package/out/runtime/api.d.ts.map +1 -1
  17. package/out/runtime/api.js +0 -14
  18. package/out/runtime/api.js.map +1 -1
  19. package/out/runtime/defs.d.ts +0 -1
  20. package/out/runtime/defs.d.ts.map +1 -1
  21. package/out/runtime/defs.js +1 -2
  22. package/out/runtime/defs.js.map +1 -1
  23. package/out/runtime/embeddings/chunker.d.ts +0 -18
  24. package/out/runtime/embeddings/chunker.d.ts.map +1 -1
  25. package/out/runtime/embeddings/chunker.js +15 -47
  26. package/out/runtime/embeddings/chunker.js.map +1 -1
  27. package/out/runtime/embeddings/openai.d.ts.map +1 -1
  28. package/out/runtime/embeddings/openai.js +11 -22
  29. package/out/runtime/embeddings/openai.js.map +1 -1
  30. package/out/runtime/embeddings/provider.d.ts +0 -1
  31. package/out/runtime/embeddings/provider.d.ts.map +1 -1
  32. package/out/runtime/embeddings/provider.js +1 -20
  33. package/out/runtime/embeddings/provider.js.map +1 -1
  34. package/out/runtime/exec-graph.js +5 -5
  35. package/out/runtime/exec-graph.js.map +1 -1
  36. package/out/runtime/interpreter.d.ts +4 -4
  37. package/out/runtime/interpreter.d.ts.map +1 -1
  38. package/out/runtime/interpreter.js +23 -30
  39. package/out/runtime/interpreter.js.map +1 -1
  40. package/out/runtime/loader.d.ts.map +1 -1
  41. package/out/runtime/loader.js +6 -2
  42. package/out/runtime/loader.js.map +1 -1
  43. package/out/runtime/logger.d.ts.map +1 -1
  44. package/out/runtime/logger.js +1 -8
  45. package/out/runtime/logger.js.map +1 -1
  46. package/out/runtime/module.d.ts +0 -6
  47. package/out/runtime/module.d.ts.map +1 -1
  48. package/out/runtime/module.js +1 -58
  49. package/out/runtime/module.js.map +1 -1
  50. package/out/runtime/modules/ai.d.ts +4 -4
  51. package/out/runtime/modules/ai.d.ts.map +1 -1
  52. package/out/runtime/modules/ai.js +70 -166
  53. package/out/runtime/modules/ai.js.map +1 -1
  54. package/out/runtime/modules/auth.d.ts.map +1 -1
  55. package/out/runtime/modules/auth.js +6 -4
  56. package/out/runtime/modules/auth.js.map +1 -1
  57. package/out/runtime/monitor.d.ts +2 -1
  58. package/out/runtime/monitor.d.ts.map +1 -1
  59. package/out/runtime/monitor.js +5 -1
  60. package/out/runtime/monitor.js.map +1 -1
  61. package/out/runtime/resolvers/sqldb/database.d.ts.map +1 -1
  62. package/out/runtime/resolvers/sqldb/database.js +126 -128
  63. package/out/runtime/resolvers/sqldb/database.js.map +1 -1
  64. package/out/runtime/resolvers/sqldb/impl.d.ts +0 -1
  65. package/out/runtime/resolvers/sqldb/impl.d.ts.map +1 -1
  66. package/out/runtime/resolvers/sqldb/impl.js +0 -3
  67. package/out/runtime/resolvers/sqldb/impl.js.map +1 -1
  68. package/out/runtime/services/documentFetcher.d.ts.map +1 -1
  69. package/out/runtime/services/documentFetcher.js +6 -21
  70. package/out/runtime/services/documentFetcher.js.map +1 -1
  71. package/out/runtime/state.d.ts +0 -14
  72. package/out/runtime/state.d.ts.map +1 -1
  73. package/out/runtime/state.js +0 -28
  74. package/out/runtime/state.js.map +1 -1
  75. package/package.json +19 -19
  76. package/src/language/agentlang.langium +2 -2
  77. package/src/language/generated/ast.ts +2 -12
  78. package/src/language/generated/grammar.ts +18 -52
  79. package/src/language/parser.ts +9 -2
  80. package/src/runtime/api.ts +0 -15
  81. package/src/runtime/defs.ts +1 -2
  82. package/src/runtime/embeddings/chunker.ts +14 -52
  83. package/src/runtime/embeddings/openai.ts +9 -27
  84. package/src/runtime/embeddings/provider.ts +1 -22
  85. package/src/runtime/exec-graph.ts +4 -4
  86. package/src/runtime/interpreter.ts +24 -29
  87. package/src/runtime/loader.ts +10 -2
  88. package/src/runtime/logger.ts +1 -12
  89. package/src/runtime/module.ts +1 -64
  90. package/src/runtime/modules/ai.ts +81 -206
  91. package/src/runtime/modules/auth.ts +6 -4
  92. package/src/runtime/monitor.ts +10 -1
  93. package/src/runtime/resolvers/sqldb/database.ts +130 -142
  94. package/src/runtime/resolvers/sqldb/impl.ts +0 -4
  95. package/src/runtime/services/documentFetcher.ts +6 -21
  96. package/src/runtime/state.ts +0 -29
  97. package/out/runtime/document-retriever.d.ts +0 -24
  98. package/out/runtime/document-retriever.d.ts.map +0 -1
  99. package/out/runtime/document-retriever.js +0 -258
  100. package/out/runtime/document-retriever.js.map +0 -1
  101. package/out/runtime/resolvers/vector/lancedb-store.d.ts +0 -16
  102. package/out/runtime/resolvers/vector/lancedb-store.d.ts.map +0 -1
  103. package/out/runtime/resolvers/vector/lancedb-store.js +0 -159
  104. package/out/runtime/resolvers/vector/lancedb-store.js.map +0 -1
  105. package/out/runtime/resolvers/vector/types.d.ts +0 -32
  106. package/out/runtime/resolvers/vector/types.d.ts.map +0 -1
  107. package/out/runtime/resolvers/vector/types.js +0 -2
  108. package/out/runtime/resolvers/vector/types.js.map +0 -1
  109. package/src/runtime/document-retriever.ts +0 -311
  110. package/src/runtime/resolvers/vector/lancedb-store.ts +0 -187
  111. package/src/runtime/resolvers/vector/types.ts +0 -39
@@ -26,7 +26,6 @@ import {
26
26
  asJSONSchema,
27
27
  Decision,
28
28
  fetchModule,
29
- getAllDocumentsForTopics,
30
29
  getDecision,
31
30
  getGlobalRetry,
32
31
  Instance,
@@ -38,9 +37,7 @@ import {
38
37
  newInstanceAttributes,
39
38
  objectToInstanceAttributes,
40
39
  Record,
41
- registerTopic as registerTopicInRegistry,
42
40
  resolveDocumentAliases,
43
- resolveTopicNames,
44
41
  Retry,
45
42
  } from '../module.js';
46
43
  import { provider } from '../agents/registry.js';
@@ -74,10 +71,9 @@ import {
74
71
  import { logger } from '../logger.js';
75
72
  import { FlowStep } from '../agents/flows.js';
76
73
  import { Statement } from '../../language/generated/ast.js';
77
- import { getKnowledgeGraphConfig, isMonitoringEnabled, TtlCache } from '../state.js';
74
+ import { isMonitoringEnabled, TtlCache } from '../state.js';
78
75
  import { isNodeEnv } from '../../utils/runtime.js';
79
76
  import { getFileSystem } from '../../utils/fs-utils.js';
80
- import { getDocumentRetriever } from '../document-retriever.js';
81
77
 
82
78
  export const CoreAIModuleName = makeCoreModuleName('ai');
83
79
  export const AgentEntityName = 'Agent';
@@ -148,10 +144,10 @@ entity ${AgentEntityName} {
148
144
  stateless Boolean @default(false),
149
145
  instruction String @optional,
150
146
  tools String @optional, // comma-separated list of tool names
151
- documents String @optional, // list of document names
152
- topics String @optional, // list of topic names
147
+ documents String @optional, // comma-separated list of document names
153
148
  channels String @optional, // comma-separated list of channel names
154
- role String @optional,
149
+ goal String @optional,
150
+ role String,
155
151
  flows String @optional,
156
152
  validate String @optional,
157
153
  retry String @optional,
@@ -196,15 +192,6 @@ workflow processDoc {
196
192
  await ai.fetchAndCreateDocument(doc.title, doc.url, doc.retrievalConfig, doc.embeddingConfig)
197
193
  }
198
194
 
199
- event topic {
200
- name String,
201
- documents String @optional // comma-separated or array of document titles
202
- }
203
-
204
- workflow processTopic {
205
- await ai.registerTopic(topic.name, topic.documents)
206
- }
207
-
208
195
  entity Directive {
209
196
  id UUID @id @default(uuid()),
210
197
  agentFqName String @indexed,
@@ -297,7 +284,7 @@ type AgentInstructionActivator = {
297
284
  provider: AgentServiceProvider;
298
285
  userMessage: string;
299
286
  agentInstruction: string;
300
- agentRole: string | undefined;
287
+ agentGoal: string | undefined;
301
288
  };
302
289
 
303
290
  const MAX_USER_DEFINED_GLOSSARY = 20;
@@ -387,10 +374,10 @@ export class AgentInstance {
387
374
  type: string = 'chat';
388
375
  tools: string | undefined;
389
376
  documents: string | undefined;
390
- topics: string | undefined;
391
377
  channels: string | undefined;
392
378
  runWorkflows: boolean = true;
393
- role: string | undefined;
379
+ goal: string | undefined;
380
+ role: string = '';
394
381
  flows: string | undefined;
395
382
  validate: string | undefined;
396
383
  retry: string | undefined;
@@ -661,7 +648,7 @@ export class AgentInstance {
661
648
  activator: AgentInstructionActivator
662
649
  ): Promise<string> {
663
650
  const fqName = this.getFqName();
664
- const ins = this.role ? `${this.role}\n${this.instruction || ''}` : this.instruction || '';
651
+ const ins = this.goal ? `${this.goal}\n${this.instruction || ''}` : this.instruction || '';
665
652
  let finalInstruction = `${ins} ${await this.directivesAsString(fqName, activator)}`;
666
653
  const staticGls = getAgentGlossary(fqName) || [];
667
654
  let userGls = await this.getUserDefinedAgentGlossary(fqName);
@@ -925,7 +912,7 @@ Only return a pure JSON object with no extra text, annotations etc.`;
925
912
  provider: p,
926
913
  userMessage: message,
927
914
  agentInstruction: this.instruction,
928
- agentRole: this.role,
915
+ agentGoal: this.goal,
929
916
  };
930
917
  if (sess) {
931
918
  msgs = sess.lookup('messages');
@@ -1142,139 +1129,93 @@ Only return a pure JSON object with no extra text, annotations etc.`;
1142
1129
  return result;
1143
1130
  }
1144
1131
 
1145
- private async maybeAddRelevantDocuments(message: string, _env: Environment): Promise<string> {
1146
- const hasDocuments = this.documents && this.documents.length > 0;
1147
- const hasTopics = this.topics && this.topics.length > 0;
1148
-
1149
- if (!hasDocuments && !hasTopics) {
1150
- return message;
1151
- }
1152
-
1153
- try {
1154
- let containerTags: string[] = [];
1155
- let topicDocumentTitles: string[] = [];
1156
-
1157
- if (hasTopics) {
1158
- const topicNames = resolveTopicNames(this.topics!);
1159
- containerTags = topicNames;
1160
- topicDocumentTitles = getAllDocumentsForTopics(topicNames);
1161
- }
1162
-
1163
- if (containerTags.length === 0) {
1164
- containerTags = [this.getFqName()];
1165
- }
1166
-
1167
- let documentTitles: string[] = [];
1168
- let documentRefs: string[] = [];
1169
-
1170
- if (hasDocuments) {
1171
- const documentEntries = this.documents!.split(',')
1172
- .map(d => d.trim())
1173
- .filter(Boolean);
1174
- documentTitles = resolveDocumentAliases(documentEntries);
1175
- documentRefs = documentEntries.filter(d => d.startsWith('document-service://'));
1176
- }
1132
+ private async maybeAddRelevantDocuments(message: string, env: Environment): Promise<string> {
1133
+ if (this.documents && this.documents.length > 0) {
1134
+ try {
1135
+ const docNames = this.documents.split(',').map(d => d.trim());
1136
+ const docTitles = resolveDocumentAliases(docNames);
1177
1137
 
1178
- const allDocumentTitles = [...new Set([...topicDocumentTitles, ...documentTitles])];
1138
+ const searchQuery = message;
1179
1139
 
1180
- const kgConfig = getKnowledgeGraphConfig();
1181
- const serviceUrl = kgConfig?.serviceUrl?.trim() || process.env.KNOWLEDGE_SERVICE_URL || null;
1140
+ try {
1141
+ const semanticResult: any[] = await parseHelper(
1142
+ `{${CoreAIModuleName}/Document {content? "${searchQuery.replace(/"/g, '\\"')}"}}`,
1143
+ env
1144
+ );
1182
1145
 
1183
- if (serviceUrl) {
1184
- return await this.queryRemoteKnowledgeService(
1185
- message,
1186
- serviceUrl,
1187
- containerTags,
1188
- allDocumentTitles,
1189
- documentRefs
1190
- );
1191
- }
1146
+ if (semanticResult && semanticResult.length > 0) {
1147
+ const docs: Instance[] = [];
1148
+ for (const doc of semanticResult) {
1149
+ const docTitle = doc.lookup ? doc.lookup('title') : doc.title;
1150
+ if (AgentInstance.docTitlesMatch(docTitle, docTitles)) {
1151
+ docs.push(
1152
+ doc instanceof Instance
1153
+ ? doc
1154
+ : Instance.newWithAttributes(doc, new Map(Object.entries(doc)))
1155
+ );
1156
+ }
1157
+ }
1192
1158
 
1193
- // Local mode: embed documents into pgvector/lancedb and query
1194
- const retriever = getDocumentRetriever();
1195
- const aiModule = isModule(DefaultModuleName + '.ai')
1196
- ? fetchModule(DefaultModuleName + '.ai')
1197
- : null;
1198
- if (aiModule) {
1199
- for (const title of allDocumentTitles) {
1200
- const url = aiModule.getDocument(title);
1201
- if (url) {
1202
- await retriever.processDocument(title, url);
1159
+ if (docs.length > 0) {
1160
+ return message.concat('\n\nRelevant context from documents:\n').concat(
1161
+ docs
1162
+ .map((v: Instance) => {
1163
+ return `Document: ${v.lookup('title')}\n${v.lookup('content') as string}`;
1164
+ })
1165
+ .join('\n\n---\n\n')
1166
+ );
1167
+ }
1203
1168
  }
1169
+ } catch (semanticErr) {
1170
+ logger.debug(
1171
+ `Semantic search is not available, falling back to title-based filtering: ${semanticErr}`
1172
+ );
1204
1173
  }
1205
- }
1206
1174
 
1207
- const contextString = await retriever.query(
1208
- message,
1209
- allDocumentTitles.length > 0 ? allDocumentTitles : undefined,
1210
- 10
1211
- );
1175
+ const result: any[] = await parseHelper(`{${CoreAIModuleName}/Document? {}}`, env);
1176
+ if (result && result.length > 0) {
1177
+ const docs: Instance[] = [];
1178
+ for (let i = 0; i < result.length; ++i) {
1179
+ const v: any = result[i];
1180
+ const docTitle: string | undefined = AgentInstance.getDocumentTitle(v);
1181
+
1182
+ if (docTitle && docTitles.includes(docTitle)) {
1183
+ if (v instanceof Instance) {
1184
+ docs.push(v);
1185
+ }
1186
+ }
1187
+ }
1212
1188
 
1213
- if (contextString.trim().length > 0) {
1214
- return message.concat('\n\nRelevant context from documents:\n').concat(contextString);
1189
+ if (docs.length > 0) {
1190
+ return message.concat('\n\nRelevant context from documents:\n').concat(
1191
+ docs
1192
+ .map((v: Instance) => {
1193
+ return v.lookup('content') as string;
1194
+ })
1195
+ .join('\n\n')
1196
+ );
1197
+ }
1198
+ }
1199
+ } catch (err) {
1200
+ logger.debug(`Error retrieving documents: ${err}`);
1215
1201
  }
1216
- } catch (err) {
1217
- logger.debug(`[KNOWLEDGE] Knowledge retrieval failed: ${err}`);
1218
1202
  }
1219
-
1220
1203
  return message;
1221
1204
  }
1222
1205
 
1223
- private async queryRemoteKnowledgeService(
1224
- message: string,
1225
- serviceUrl: string,
1226
- containerTags: string[],
1227
- documentTitles: string[],
1228
- documentRefs: string[]
1229
- ): Promise<string> {
1230
- const options = {
1231
- chunkLimit: 10,
1232
- entityLimit: 20,
1233
- includeChunks: true,
1234
- includeEntities: true,
1235
- includeEdges: true,
1236
- documentTitles: documentTitles.length > 0 ? documentTitles : undefined,
1237
- documentRefs: documentRefs.length > 0 ? documentRefs : undefined,
1238
- };
1239
-
1240
- let response = await fetch(`${serviceUrl}/api/knowledge/query`, {
1241
- method: 'POST',
1242
- headers: { 'Content-Type': 'application/json' },
1243
- body: JSON.stringify({ query: message, containerTags, ...options }),
1244
- });
1245
-
1246
- if (!response.ok) {
1247
- response = await fetch(`${serviceUrl}/knowledge.core/ApiKnowledgeQuery`, {
1248
- method: 'POST',
1249
- headers: { 'Content-Type': 'application/json' },
1250
- body: JSON.stringify({
1251
- queryText: message,
1252
- containerTagsJson: JSON.stringify(containerTags),
1253
- documentTitlesJson: JSON.stringify(options.documentTitles || []),
1254
- documentRefsJson: JSON.stringify(options.documentRefs || []),
1255
- optionsJson: JSON.stringify({
1256
- includeChunks: options.includeChunks,
1257
- includeEntities: options.includeEntities,
1258
- includeEdges: options.includeEdges,
1259
- chunkLimit: options.chunkLimit,
1260
- entityLimit: options.entityLimit,
1261
- }),
1262
- }),
1263
- });
1264
- }
1206
+ private static docTitlesMatch(title: string | undefined, docNames: string[]): boolean {
1207
+ return title !== undefined && docNames.includes(title);
1208
+ }
1265
1209
 
1266
- if (response.ok) {
1267
- const rawPayload: any = await response.json();
1268
- const first = Array.isArray(rawPayload) ? rawPayload[0] : rawPayload;
1269
- const payload =
1270
- first && typeof first === 'object' && first.KnowledgeQuery ? first.KnowledgeQuery : first;
1271
- const contextString = payload?.contextString || '';
1272
- if (contextString.trim().length > 0) {
1273
- return message.concat('\n\nRelevant context from documents:\n').concat(contextString);
1274
- }
1210
+ private static getDocumentTitle(doc: any): string | undefined {
1211
+ if (typeof doc.lookup === 'function') {
1212
+ return doc.lookup('title') as string | undefined;
1213
+ } else if (doc.attributes) {
1214
+ return doc.attributes.get('title') as string | undefined;
1215
+ } else if (doc.title) {
1216
+ return doc.title;
1275
1217
  }
1276
-
1277
- return message;
1218
+ return undefined;
1278
1219
  }
1279
1220
 
1280
1221
  private static ToolsCache = new Map<string, string>();
@@ -1734,72 +1675,6 @@ export async function loadFlowStep(chatId: string, step: string): Promise<Instan
1734
1675
  }
1735
1676
  }
1736
1677
 
1737
- export async function registerTopic(
1738
- name: string,
1739
- documents: string | undefined,
1740
- _env: Environment
1741
- ): Promise<any> {
1742
- // Register in local registry
1743
- registerTopicInRegistry(name, documents ?? undefined);
1744
-
1745
- // Sync to knowledge service if configured
1746
- const kgConfig = getKnowledgeGraphConfig();
1747
- const serviceUrl = kgConfig?.serviceUrl?.trim() || process.env.KNOWLEDGE_SERVICE_URL || null;
1748
-
1749
- if (serviceUrl) {
1750
- try {
1751
- // Parse document list
1752
- const docList = documents
1753
- ? documents
1754
- .split(',')
1755
- .map(d => d.trim())
1756
- .filter(Boolean)
1757
- : [];
1758
-
1759
- // Create or update topic in knowledge service
1760
- let response = await fetch(`${serviceUrl}/api/knowledge/topics`, {
1761
- method: 'POST',
1762
- headers: {
1763
- 'Content-Type': 'application/json',
1764
- },
1765
- body: JSON.stringify({
1766
- name,
1767
- description: `Topic ${name} with ${docList.length} documents`,
1768
- documentTitles: docList,
1769
- }),
1770
- });
1771
-
1772
- if (!response.ok) {
1773
- // Fallback to Agentlang entity path for deployed knowledge-service
1774
- response = await fetch(`${serviceUrl}/knowledge.core/Topic`, {
1775
- method: 'POST',
1776
- headers: {
1777
- 'Content-Type': 'application/json',
1778
- },
1779
- body: JSON.stringify({
1780
- name,
1781
- description: `Topic ${name} with ${docList.length} documents`,
1782
- type: 'manual',
1783
- documentCount: docList.length,
1784
- }),
1785
- });
1786
- }
1787
-
1788
- if (!response.ok) {
1789
- const errorText = await response.text();
1790
- logger.debug(`[KNOWLEDGE] Failed to sync topic to service: ${errorText}`);
1791
- } else {
1792
- logger.debug(`[KNOWLEDGE] Synced topic "${name}" to knowledge service`);
1793
- }
1794
- } catch (err) {
1795
- // Don't fail topic registration if service sync fails
1796
- logger.debug(`[KNOWLEDGE] Error syncing topic to service: ${err}`);
1797
- }
1798
- }
1799
-
1800
- return { topic: { name, documents: documents ?? '' } };
1801
- }
1802
-
1803
1678
  export async function fetchAndCreateDocument(
1804
1679
  title: string,
1805
1680
  url: string,
@@ -960,10 +960,12 @@ export async function userHasPermissions(
960
960
  UserRoleCache.set(userId, userRoles);
961
961
  }
962
962
  let tempRoles = userRoles;
963
- const escalatedRole = env.getEscalatedRole();
964
- if (escalatedRole) {
965
- tempRoles = userRoles.slice();
966
- tempRoles.push(escalatedRole);
963
+ const assumedRole = env.getAssumedRole();
964
+ if (assumedRole) {
965
+ tempRoles = [assumedRole];
966
+ if (!RolePermissionsCache.get(assumedRole)) {
967
+ await updatePermissionCacheForRole(assumedRole, env);
968
+ }
967
969
  }
968
970
  if (
969
971
  tempRoles &&
@@ -179,6 +179,7 @@ export class Monitor {
179
179
  private id: string;
180
180
  private eventInstance: Instance | undefined;
181
181
  private user: string | undefined;
182
+ private role: string | undefined;
182
183
  private entries: (MonitorEntry | Monitor)[] = new Array<MonitorEntry | Monitor>();
183
184
  private parent: Monitor | undefined = undefined;
184
185
  private lastEntry: MonitorEntry | undefined = undefined;
@@ -189,10 +190,15 @@ export class Monitor {
189
190
 
190
191
  private static MAX_REGISTRY_SIZE = 25;
191
192
 
192
- constructor(eventInstance?: Instance | undefined, user?: string | undefined) {
193
+ constructor(
194
+ eventInstance?: Instance | undefined,
195
+ user?: string | undefined,
196
+ role?: string | undefined
197
+ ) {
193
198
  this.eventInstance = eventInstance;
194
199
  this.id = eventInstance ? eventInstance.getId() : crypto.randomUUID();
195
200
  this.user = user;
201
+ this.role = role;
196
202
  this.timestamp = Date.now();
197
203
  while (monitorRegistry.length >= Monitor.MAX_REGISTRY_SIZE) {
198
204
  monitorRegistry.shift();
@@ -405,6 +411,9 @@ export class Monitor {
405
411
  if (this.user) {
406
412
  r.user = this.user;
407
413
  }
414
+ if (this.role) {
415
+ r.role = this.role;
416
+ }
408
417
  r.timestamp = this.timestamp;
409
418
  if (this.flowResult !== undefined) {
410
419
  let fr = this.flowResult;