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.
- package/README.md +22 -9
- package/out/extension/main.cjs +250 -250
- package/out/extension/main.cjs.map +2 -2
- package/out/language/generated/ast.d.ts +7 -7
- package/out/language/generated/ast.d.ts.map +1 -1
- package/out/language/generated/grammar.js +2 -2
- package/out/language/main.cjs +506 -506
- package/out/language/main.cjs.map +3 -3
- package/out/language/parser.d.ts.map +1 -1
- package/out/language/parser.js +9 -2
- package/out/language/parser.js.map +1 -1
- package/out/language/syntax.d.ts +2 -2
- package/out/language/syntax.d.ts.map +1 -1
- package/out/runtime/api.d.ts.map +1 -1
- package/out/runtime/api.js +0 -14
- package/out/runtime/api.js.map +1 -1
- package/out/runtime/defs.d.ts +0 -1
- package/out/runtime/defs.d.ts.map +1 -1
- package/out/runtime/defs.js +1 -2
- package/out/runtime/defs.js.map +1 -1
- package/out/runtime/embeddings/chunker.d.ts +0 -18
- package/out/runtime/embeddings/chunker.d.ts.map +1 -1
- package/out/runtime/embeddings/chunker.js +15 -47
- package/out/runtime/embeddings/chunker.js.map +1 -1
- package/out/runtime/embeddings/openai.d.ts.map +1 -1
- package/out/runtime/embeddings/openai.js +11 -22
- package/out/runtime/embeddings/openai.js.map +1 -1
- package/out/runtime/embeddings/provider.d.ts +0 -1
- package/out/runtime/embeddings/provider.d.ts.map +1 -1
- package/out/runtime/embeddings/provider.js +1 -20
- package/out/runtime/embeddings/provider.js.map +1 -1
- package/out/runtime/exec-graph.js +5 -5
- package/out/runtime/exec-graph.js.map +1 -1
- package/out/runtime/interpreter.d.ts +4 -4
- package/out/runtime/interpreter.d.ts.map +1 -1
- package/out/runtime/interpreter.js +27 -16
- package/out/runtime/interpreter.js.map +1 -1
- package/out/runtime/loader.d.ts.map +1 -1
- package/out/runtime/loader.js +6 -2
- package/out/runtime/loader.js.map +1 -1
- package/out/runtime/logger.d.ts.map +1 -1
- package/out/runtime/logger.js +1 -8
- package/out/runtime/logger.js.map +1 -1
- package/out/runtime/module.d.ts +0 -6
- package/out/runtime/module.d.ts.map +1 -1
- package/out/runtime/module.js +1 -58
- package/out/runtime/module.js.map +1 -1
- package/out/runtime/modules/ai.d.ts +4 -4
- package/out/runtime/modules/ai.d.ts.map +1 -1
- package/out/runtime/modules/ai.js +70 -166
- package/out/runtime/modules/ai.js.map +1 -1
- package/out/runtime/modules/auth.d.ts.map +1 -1
- package/out/runtime/modules/auth.js +6 -4
- package/out/runtime/modules/auth.js.map +1 -1
- package/out/runtime/modules/core.d.ts.map +1 -1
- package/out/runtime/modules/core.js +3 -0
- package/out/runtime/modules/core.js.map +1 -1
- package/out/runtime/modules/messaging.d.ts +10 -0
- package/out/runtime/modules/messaging.d.ts.map +1 -0
- package/out/runtime/modules/messaging.js +210 -0
- package/out/runtime/modules/messaging.js.map +1 -0
- package/out/runtime/monitor.d.ts +2 -1
- package/out/runtime/monitor.d.ts.map +1 -1
- package/out/runtime/monitor.js +5 -1
- package/out/runtime/monitor.js.map +1 -1
- package/out/runtime/resolvers/sqldb/database.d.ts.map +1 -1
- package/out/runtime/resolvers/sqldb/database.js +126 -128
- package/out/runtime/resolvers/sqldb/database.js.map +1 -1
- package/out/runtime/resolvers/sqldb/impl.d.ts +0 -1
- package/out/runtime/resolvers/sqldb/impl.d.ts.map +1 -1
- package/out/runtime/resolvers/sqldb/impl.js +0 -3
- package/out/runtime/resolvers/sqldb/impl.js.map +1 -1
- package/out/runtime/services/documentFetcher.d.ts.map +1 -1
- package/out/runtime/services/documentFetcher.js +6 -21
- package/out/runtime/services/documentFetcher.js.map +1 -1
- package/out/runtime/state.d.ts +0 -14
- package/out/runtime/state.d.ts.map +1 -1
- package/out/runtime/state.js +0 -28
- package/out/runtime/state.js.map +1 -1
- package/package.json +19 -19
- package/src/language/agentlang.langium +2 -2
- package/src/language/generated/ast.ts +7 -7
- package/src/language/generated/grammar.ts +2 -2
- package/src/language/parser.ts +9 -2
- package/src/language/syntax.ts +2 -2
- package/src/runtime/api.ts +0 -15
- package/src/runtime/defs.ts +1 -2
- package/src/runtime/embeddings/chunker.ts +14 -52
- package/src/runtime/embeddings/openai.ts +9 -27
- package/src/runtime/embeddings/provider.ts +1 -22
- package/src/runtime/exec-graph.ts +4 -4
- package/src/runtime/interpreter.ts +32 -17
- package/src/runtime/loader.ts +10 -2
- package/src/runtime/logger.ts +1 -12
- package/src/runtime/module.ts +1 -64
- package/src/runtime/modules/ai.ts +81 -206
- package/src/runtime/modules/auth.ts +6 -4
- package/src/runtime/modules/core.ts +4 -0
- package/src/runtime/modules/messaging.ts +228 -0
- package/src/runtime/monitor.ts +10 -1
- package/src/runtime/resolvers/sqldb/database.ts +130 -142
- package/src/runtime/resolvers/sqldb/impl.ts +0 -4
- package/src/runtime/services/documentFetcher.ts +6 -21
- package/src/runtime/state.ts +0 -29
- package/out/runtime/document-retriever.d.ts +0 -24
- package/out/runtime/document-retriever.d.ts.map +0 -1
- package/out/runtime/document-retriever.js +0 -258
- package/out/runtime/document-retriever.js.map +0 -1
- package/out/runtime/resolvers/vector/lancedb-store.d.ts +0 -16
- package/out/runtime/resolvers/vector/lancedb-store.d.ts.map +0 -1
- package/out/runtime/resolvers/vector/lancedb-store.js +0 -159
- package/out/runtime/resolvers/vector/lancedb-store.js.map +0 -1
- package/out/runtime/resolvers/vector/types.d.ts +0 -32
- package/out/runtime/resolvers/vector/types.d.ts.map +0 -1
- package/out/runtime/resolvers/vector/types.js +0 -2
- package/out/runtime/resolvers/vector/types.js.map +0 -1
- package/src/runtime/document-retriever.ts +0 -311
- package/src/runtime/resolvers/vector/lancedb-store.ts +0 -187
- 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
|
|
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.
|
|
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
|
-
|
|
312
|
-
this.
|
|
311
|
+
setAssumedRole(s: string): Environment {
|
|
312
|
+
this.assumedRole = s;
|
|
313
313
|
return this;
|
|
314
314
|
}
|
|
315
315
|
|
|
316
|
-
|
|
317
|
-
return this.
|
|
316
|
+
getAssumedRole(): string | undefined {
|
|
317
|
+
return this.assumedRole;
|
|
318
318
|
}
|
|
319
319
|
|
|
320
|
-
|
|
321
|
-
this.
|
|
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.
|
|
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?.
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
2175
|
-
invokeDebugMsg = `${invokeDebugMsg}
|
|
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);
|
package/src/runtime/loader.ts
CHANGED
|
@@ -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 (
|
|
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);
|
package/src/runtime/logger.ts
CHANGED
|
@@ -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
|
|
47
|
+
transports: [fileTransport],
|
|
59
48
|
});
|
|
60
49
|
} else {
|
|
61
50
|
function mkLogger(tag: string): Function {
|
package/src/runtime/module.ts
CHANGED
|
@@ -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 {
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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,
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
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
|
-
|
|
1138
|
+
const searchQuery = message;
|
|
1179
1139
|
|
|
1180
|
-
|
|
1181
|
-
|
|
1140
|
+
try {
|
|
1141
|
+
const semanticResult: any[] = await parseHelper(
|
|
1142
|
+
`{${CoreAIModuleName}/Document {content? "${searchQuery.replace(/"/g, '\\"')}"}}`,
|
|
1143
|
+
env
|
|
1144
|
+
);
|
|
1182
1145
|
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
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
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
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
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
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
|
-
|
|
1214
|
-
|
|
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
|
|
1224
|
-
|
|
1225
|
-
|
|
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
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
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
|
|
964
|
-
if (
|
|
965
|
-
tempRoles =
|
|
966
|
-
|
|
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 &&
|