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