agentlang 0.10.3 → 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 (119) 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 +7 -7
  5. package/out/language/generated/ast.d.ts.map +1 -1
  6. package/out/language/generated/grammar.js +2 -2
  7. package/out/language/main.cjs +506 -506
  8. package/out/language/main.cjs.map +3 -3
  9. package/out/language/parser.d.ts.map +1 -1
  10. package/out/language/parser.js +9 -2
  11. package/out/language/parser.js.map +1 -1
  12. package/out/language/syntax.d.ts +2 -2
  13. package/out/language/syntax.d.ts.map +1 -1
  14. package/out/runtime/api.d.ts.map +1 -1
  15. package/out/runtime/api.js +0 -14
  16. package/out/runtime/api.js.map +1 -1
  17. package/out/runtime/defs.d.ts +0 -1
  18. package/out/runtime/defs.d.ts.map +1 -1
  19. package/out/runtime/defs.js +1 -2
  20. package/out/runtime/defs.js.map +1 -1
  21. package/out/runtime/embeddings/chunker.d.ts +0 -18
  22. package/out/runtime/embeddings/chunker.d.ts.map +1 -1
  23. package/out/runtime/embeddings/chunker.js +15 -47
  24. package/out/runtime/embeddings/chunker.js.map +1 -1
  25. package/out/runtime/embeddings/openai.d.ts.map +1 -1
  26. package/out/runtime/embeddings/openai.js +11 -22
  27. package/out/runtime/embeddings/openai.js.map +1 -1
  28. package/out/runtime/embeddings/provider.d.ts +0 -1
  29. package/out/runtime/embeddings/provider.d.ts.map +1 -1
  30. package/out/runtime/embeddings/provider.js +1 -20
  31. package/out/runtime/embeddings/provider.js.map +1 -1
  32. package/out/runtime/exec-graph.js +5 -5
  33. package/out/runtime/exec-graph.js.map +1 -1
  34. package/out/runtime/interpreter.d.ts +4 -4
  35. package/out/runtime/interpreter.d.ts.map +1 -1
  36. package/out/runtime/interpreter.js +27 -16
  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 +6 -2
  40. package/out/runtime/loader.js.map +1 -1
  41. package/out/runtime/logger.d.ts.map +1 -1
  42. package/out/runtime/logger.js +1 -8
  43. package/out/runtime/logger.js.map +1 -1
  44. package/out/runtime/module.d.ts +0 -6
  45. package/out/runtime/module.d.ts.map +1 -1
  46. package/out/runtime/module.js +1 -58
  47. package/out/runtime/module.js.map +1 -1
  48. package/out/runtime/modules/ai.d.ts +4 -4
  49. package/out/runtime/modules/ai.d.ts.map +1 -1
  50. package/out/runtime/modules/ai.js +70 -166
  51. package/out/runtime/modules/ai.js.map +1 -1
  52. package/out/runtime/modules/auth.d.ts.map +1 -1
  53. package/out/runtime/modules/auth.js +6 -4
  54. package/out/runtime/modules/auth.js.map +1 -1
  55. package/out/runtime/modules/core.d.ts.map +1 -1
  56. package/out/runtime/modules/core.js +3 -0
  57. package/out/runtime/modules/core.js.map +1 -1
  58. package/out/runtime/modules/messaging.d.ts +10 -0
  59. package/out/runtime/modules/messaging.d.ts.map +1 -0
  60. package/out/runtime/modules/messaging.js +210 -0
  61. package/out/runtime/modules/messaging.js.map +1 -0
  62. package/out/runtime/monitor.d.ts +2 -1
  63. package/out/runtime/monitor.d.ts.map +1 -1
  64. package/out/runtime/monitor.js +5 -1
  65. package/out/runtime/monitor.js.map +1 -1
  66. package/out/runtime/resolvers/sqldb/database.d.ts.map +1 -1
  67. package/out/runtime/resolvers/sqldb/database.js +126 -128
  68. package/out/runtime/resolvers/sqldb/database.js.map +1 -1
  69. package/out/runtime/resolvers/sqldb/impl.d.ts +0 -1
  70. package/out/runtime/resolvers/sqldb/impl.d.ts.map +1 -1
  71. package/out/runtime/resolvers/sqldb/impl.js +0 -3
  72. package/out/runtime/resolvers/sqldb/impl.js.map +1 -1
  73. package/out/runtime/services/documentFetcher.d.ts.map +1 -1
  74. package/out/runtime/services/documentFetcher.js +6 -21
  75. package/out/runtime/services/documentFetcher.js.map +1 -1
  76. package/out/runtime/state.d.ts +0 -14
  77. package/out/runtime/state.d.ts.map +1 -1
  78. package/out/runtime/state.js +0 -28
  79. package/out/runtime/state.js.map +1 -1
  80. package/package.json +19 -19
  81. package/src/language/agentlang.langium +2 -2
  82. package/src/language/generated/ast.ts +7 -7
  83. package/src/language/generated/grammar.ts +2 -2
  84. package/src/language/parser.ts +9 -2
  85. package/src/language/syntax.ts +2 -2
  86. package/src/runtime/api.ts +0 -15
  87. package/src/runtime/defs.ts +1 -2
  88. package/src/runtime/embeddings/chunker.ts +14 -52
  89. package/src/runtime/embeddings/openai.ts +9 -27
  90. package/src/runtime/embeddings/provider.ts +1 -22
  91. package/src/runtime/exec-graph.ts +4 -4
  92. package/src/runtime/interpreter.ts +32 -17
  93. package/src/runtime/loader.ts +10 -2
  94. package/src/runtime/logger.ts +1 -12
  95. package/src/runtime/module.ts +1 -64
  96. package/src/runtime/modules/ai.ts +81 -206
  97. package/src/runtime/modules/auth.ts +6 -4
  98. package/src/runtime/modules/core.ts +4 -0
  99. package/src/runtime/modules/messaging.ts +228 -0
  100. package/src/runtime/monitor.ts +10 -1
  101. package/src/runtime/resolvers/sqldb/database.ts +130 -142
  102. package/src/runtime/resolvers/sqldb/impl.ts +0 -4
  103. package/src/runtime/services/documentFetcher.ts +6 -21
  104. package/src/runtime/state.ts +0 -29
  105. package/out/runtime/document-retriever.d.ts +0 -24
  106. package/out/runtime/document-retriever.d.ts.map +0 -1
  107. package/out/runtime/document-retriever.js +0 -258
  108. package/out/runtime/document-retriever.js.map +0 -1
  109. package/out/runtime/resolvers/vector/lancedb-store.d.ts +0 -16
  110. package/out/runtime/resolvers/vector/lancedb-store.d.ts.map +0 -1
  111. package/out/runtime/resolvers/vector/lancedb-store.js +0 -159
  112. package/out/runtime/resolvers/vector/lancedb-store.js.map +0 -1
  113. package/out/runtime/resolvers/vector/types.d.ts +0 -32
  114. package/out/runtime/resolvers/vector/types.d.ts.map +0 -1
  115. package/out/runtime/resolvers/vector/types.js +0 -2
  116. package/out/runtime/resolvers/vector/types.js.map +0 -1
  117. package/src/runtime/document-retriever.ts +0 -311
  118. package/src/runtime/resolvers/vector/lancedb-store.ts +0 -187
  119. package/src/runtime/resolvers/vector/types.ts +0 -39
@@ -182,7 +182,7 @@ export class Environment extends Instance {
182
182
  private agentMode: 'chat' | 'planner' | undefined = undefined;
183
183
  private agentChatId: string | undefined = undefined;
184
184
  private monitor: Monitor | undefined = undefined;
185
- private escalatedRole: string | undefined;
185
+ private assumedRole: string | undefined;
186
186
  private activeChatId: string | undefined;
187
187
 
188
188
  private activeUserData: any = undefined;
@@ -210,7 +210,7 @@ export class Environment extends Instance {
210
210
  this.eventExecutor = parent.eventExecutor;
211
211
  this.agentChatId = parent.agentChatId;
212
212
  this.monitor = parent.monitor;
213
- this.escalatedRole = parent.escalatedRole;
213
+ this.assumedRole = parent.assumedRole;
214
214
  this.activeChatId = parent.activeChatId;
215
215
  } else {
216
216
  this.activeModule = DefaultModuleName;
@@ -308,17 +308,17 @@ export class Environment extends Instance {
308
308
  return this;
309
309
  }
310
310
 
311
- setEscalatedRole(s: string): Environment {
312
- this.escalatedRole = s;
311
+ setAssumedRole(s: string): Environment {
312
+ this.assumedRole = s;
313
313
  return this;
314
314
  }
315
315
 
316
- getEscalatedRole(): string | undefined {
317
- return this.escalatedRole;
316
+ getAssumedRole(): string | undefined {
317
+ return this.assumedRole;
318
318
  }
319
319
 
320
- resetEscalatedRole(): Environment {
321
- this.escalatedRole = undefined;
320
+ resetAssumedRole(): Environment {
321
+ this.assumedRole = undefined;
322
322
  return this;
323
323
  }
324
324
 
@@ -856,7 +856,7 @@ export class Environment extends Instance {
856
856
  if (this.activeEventInstance && isCoreModule(this.activeEventInstance.moduleName)) {
857
857
  return this;
858
858
  }
859
- this.monitor = new Monitor(this.activeEventInstance, this.activeUser);
859
+ this.monitor = new Monitor(this.activeEventInstance, this.activeUser, this.assumedRole);
860
860
  }
861
861
  this.monitor.addEntry(new MonitorEntry(stmt));
862
862
  return this;
@@ -971,7 +971,7 @@ export let evaluate = async function (
971
971
  env = new Environment(eventInstance.name + '.env', activeEnv);
972
972
  env.setActiveEvent(eventInstance);
973
973
  const er = wf.getRoleEscalation();
974
- if (er) env.setEscalatedRole(er);
974
+ if (er) env.setAssumedRole(er);
975
975
  if (kernelCall) {
976
976
  env.setInKernelMode(true);
977
977
  }
@@ -1012,7 +1012,7 @@ export let evaluate = async function (
1012
1012
  throw err;
1013
1013
  }
1014
1014
  } finally {
1015
- env?.resetEscalatedRole();
1015
+ env?.resetAssumedRole();
1016
1016
  if (!txnRolledBack && env !== undefined && activeEnv === undefined) {
1017
1017
  await env.commitAllTransactions();
1018
1018
  }
@@ -1578,7 +1578,11 @@ async function maybeValidateOneOfRefs(inst: Instance, env: Environment) {
1578
1578
  }
1579
1579
  }
1580
1580
 
1581
- function maybeSetQueryClauses(inst: Instance, qopts: ExtractedQueryOptions) {
1581
+ async function maybeSetQueryClauses(
1582
+ inst: Instance,
1583
+ qopts: ExtractedQueryOptions,
1584
+ env: Environment
1585
+ ) {
1582
1586
  if (qopts.groupByClause) {
1583
1587
  inst.setGroupBy(qopts.groupByClause.colNames);
1584
1588
  }
@@ -1586,10 +1590,18 @@ function maybeSetQueryClauses(inst: Instance, qopts: ExtractedQueryOptions) {
1586
1590
  inst.setOrderBy(qopts.orderByClause.colNames, qopts.orderByClause.order === '@desc');
1587
1591
  }
1588
1592
  if (qopts.limitClause) {
1589
- inst.setLimit(qopts.limitClause.value);
1593
+ await evaluateExpression(qopts.limitClause.value, env);
1594
+ const v = env.getLastResult();
1595
+ if (typeof v === 'number') {
1596
+ inst.setLimit(v);
1597
+ }
1590
1598
  }
1591
1599
  if (qopts.offsetClause) {
1592
- inst.setOffset(qopts.offsetClause.value);
1600
+ await evaluateExpression(qopts.offsetClause.value, env);
1601
+ const v = env.getLastResult();
1602
+ if (typeof v === 'number') {
1603
+ inst.setOffset(v);
1604
+ }
1593
1605
  }
1594
1606
  }
1595
1607
 
@@ -1608,7 +1620,7 @@ async function evaluateCrudMap(crud: CrudMap, env: Environment): Promise<void> {
1608
1620
  const onlyAggregates = inst.aggregates !== undefined && qattrs === undefined;
1609
1621
  const isQueryAll = onlyAggregates || crud.name.endsWith(QuerySuffix);
1610
1622
  const distinct: boolean = qopts.distinct !== undefined;
1611
- maybeSetQueryClauses(inst, qopts);
1623
+ await maybeSetQueryClauses(inst, qopts, env);
1612
1624
  if (attrs.size > 0) {
1613
1625
  await maybeValidateOneOfRefs(inst, env);
1614
1626
  }
@@ -2171,8 +2183,8 @@ const MAX_PLANNER_RETRIES = 3;
2171
2183
  async function agentInvoke(agent: AgentInstance, msg: string, env: Environment): Promise<void> {
2172
2184
  // log invocation details
2173
2185
  let invokeDebugMsg = `\nInvoking agent ${agent.name}:`;
2174
- if (agent.role) {
2175
- invokeDebugMsg = `${invokeDebugMsg} Role=${agent.role}`;
2186
+ if (agent.goal) {
2187
+ invokeDebugMsg = `${invokeDebugMsg} Goal=${agent.goal}`;
2176
2188
  }
2177
2189
  console.debug(invokeDebugMsg);
2178
2190
  invokeDebugMsg = `\nMessage=${msg}`;
@@ -2299,6 +2311,9 @@ export async function handleAgentInvocation(
2299
2311
  env: Environment
2300
2312
  ): Promise<void> {
2301
2313
  const agent: AgentInstance = await findAgentByName(agentEventInst.name, env);
2314
+ if (agent.role) {
2315
+ env.setAssumedRole(agent.role);
2316
+ }
2302
2317
  const chatId = agentEventInst.lookup('chatId');
2303
2318
  if (chatId) {
2304
2319
  env.setActiveChatId(chatId);
@@ -832,7 +832,14 @@ async function addAgentDefinition(
832
832
  }
833
833
  const ov = v;
834
834
  if (apdef.value.id || apdef.value.ref || apdef.value.array) {
835
- if (!(apdef.name === 'instruction' || apdef.name === 'role' || apdef.name === 'llm'))
835
+ if (
836
+ !(
837
+ apdef.name === 'instruction' ||
838
+ apdef.name === 'goal' ||
839
+ apdef.name === 'role' ||
840
+ apdef.name === 'llm'
841
+ )
842
+ )
836
843
  v = `"${v}"`;
837
844
  } else if (apdef.value.str) {
838
845
  v = `"${escapeSpecialChars(v)}"`;
@@ -867,9 +874,10 @@ async function addAgentDefinition(
867
874
  }
868
875
  if (attrs.get('type') === 'planner' || attrs.get('tools')) {
869
876
  const llmn = llmName || attrs.get('llm');
877
+ const agentRole = attrs.get('role') || 'admin';
870
878
  wf = `${wf}; {${CoreAIModuleName}/${AgentEntityName}
871
879
  {name "${name}_${AgentLearnerType}", moduleName "${moduleName}", llm "${llmn}",
872
- type "${AgentLearnerType}", role "You are an agent that summarizes user-provided scenarios."}, @upsert}`;
880
+ type "${AgentLearnerType}", role "${agentRole}", goal "You are an agent that summarizes user-provided scenarios."}, @upsert}`;
873
881
  }
874
882
  (await parseWorkflow(`workflow A {${wf}}`)).statements.forEach((stmt: Statement) => {
875
883
  addStandaloneStatement(stmt, moduleName, false);
@@ -36,17 +36,6 @@ export function initializeLogger() {
36
36
  maxFiles: '7d',
37
37
  });
38
38
 
39
- // Add console transport for visibility
40
- const consoleTransport = new winston.transports.Console({
41
- level: logLevel,
42
- format: winston.format.combine(
43
- winston.format.colorize(),
44
- winston.format.printf(({ level, message }: any) => {
45
- return `${level}: ${message}`;
46
- })
47
- ),
48
- });
49
-
50
39
  logger = winston.createLogger({
51
40
  level: logLevel,
52
41
  format: winston.format.combine(
@@ -55,7 +44,7 @@ export function initializeLogger() {
55
44
  return `[${timestamp}] ${level}: ${message}`;
56
45
  })
57
46
  ),
58
- transports: [fileTransport, consoleTransport],
47
+ transports: [fileTransport],
59
48
  });
60
49
  } else {
61
50
  function mkLogger(tag: string): Function {
@@ -2859,46 +2859,6 @@ export function resolveDocumentAliases(names: string[]): string[] {
2859
2859
  return names.map((name: string) => DocumentAliasMap.get(name) ?? name);
2860
2860
  }
2861
2861
 
2862
- // TopicRegistry: maps topic name → list of document titles belonging to that topic
2863
- const TopicRegistry: Map<string, string[]> = new Map();
2864
-
2865
- export function registerTopic(name: string, documents?: string): void {
2866
- if (!name) return;
2867
- const docs = documents
2868
- ? documents
2869
- .split(',')
2870
- .map(d => d.trim())
2871
- .filter(Boolean)
2872
- : [];
2873
- TopicRegistry.set(name, docs);
2874
- }
2875
-
2876
- export function getTopicDocuments(topicName: string): string[] {
2877
- return TopicRegistry.get(topicName) ?? [];
2878
- }
2879
-
2880
- export function resolveTopicNames(topicsCsv: string): string[] {
2881
- return topicsCsv
2882
- .split(',')
2883
- .map(t => t.trim())
2884
- .filter(Boolean);
2885
- }
2886
-
2887
- export function getTopicContainerTags(topicNames: string[]): string[] {
2888
- return topicNames.filter(name => TopicRegistry.has(name));
2889
- }
2890
-
2891
- export function getAllDocumentsForTopics(topicNames: string[]): string[] {
2892
- const docs: string[] = [];
2893
- for (const name of topicNames) {
2894
- const topicDocs = TopicRegistry.get(name);
2895
- if (topicDocs) {
2896
- docs.push(...topicDocs);
2897
- }
2898
- }
2899
- return [...new Set(docs)];
2900
- }
2901
-
2902
2862
  export function addGlobalRetry(r: Retry): Retry {
2903
2863
  if (GlobalRetries === undefined) {
2904
2864
  GlobalRetries = new Array<Retry>();
@@ -2995,19 +2955,6 @@ export function fetchModuleEntry(entryName: string, moduleName: string): ModuleE
2995
2955
  const module: Module = fetchModule(moduleName);
2996
2956
  return module.getEntry(entryName);
2997
2957
  }
2998
- // UUID regex pattern
2999
- const UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
3000
-
3001
- // containerTag format: alphanumeric with dashes/underscores, no spaces
3002
- const CONTAINER_TAG_REGEX = /^[a-zA-Z0-9][a-zA-Z0-9_-]*$/;
3003
-
3004
- export function isTopicReference(value: any): boolean {
3005
- if (!isString(value)) {
3006
- return false;
3007
- }
3008
- // Topic can be a UUID or a containerTag format
3009
- return UUID_REGEX.test(value) || CONTAINER_TAG_REGEX.test(value);
3010
- }
3011
2958
 
3012
2959
  const builtInChecks = new Map([
3013
2960
  ['String', isString],
@@ -3036,7 +2983,6 @@ const builtInChecks = new Map([
3036
2983
  return true;
3037
2984
  },
3038
2985
  ],
3039
- ['Topic', isTopicReference],
3040
2986
  ]);
3041
2987
 
3042
2988
  export const builtInTypes = new Set(Array.from(builtInChecks.keys()));
@@ -3060,16 +3006,7 @@ export const propertyNames = new Set([
3060
3006
  '@comment',
3061
3007
  ]);
3062
3008
 
3063
- const TextualTypes = new Set([
3064
- 'String',
3065
- 'Email',
3066
- 'UUID',
3067
- 'DateTime',
3068
- 'Date',
3069
- 'Time',
3070
- 'Path',
3071
- 'Topic',
3072
- ]);
3009
+ const TextualTypes = new Set(['String', 'Email', 'UUID', 'DateTime', 'Date', 'Time', 'Path']);
3073
3010
 
3074
3011
  function isTextualType(type: string): boolean {
3075
3012
  return TextualTypes.has(type);
@@ -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 &&