agentlang 0.0.13 → 0.0.14
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/cli/docs.d.ts +2 -0
- package/out/cli/docs.d.ts.map +1 -0
- package/out/cli/docs.js +236 -0
- package/out/cli/docs.js.map +1 -0
- package/out/cli/main.d.ts.map +1 -1
- package/out/cli/main.js +5 -0
- package/out/cli/main.js.map +1 -1
- package/out/cli/openapi-docs.yml +695 -0
- package/out/index.d.ts +19 -0
- package/out/index.d.ts.map +1 -0
- package/out/index.js +25 -0
- package/out/index.js.map +1 -0
- package/out/language/generated/ast.d.ts +23 -12
- package/out/language/generated/ast.d.ts.map +1 -1
- package/out/language/generated/ast.js +18 -2
- package/out/language/generated/ast.js.map +1 -1
- package/out/language/generated/grammar.d.ts.map +1 -1
- package/out/language/generated/grammar.js +231 -122
- package/out/language/generated/grammar.js.map +1 -1
- package/out/language/main.cjs +243 -124
- package/out/language/main.cjs.map +2 -2
- package/out/runtime/agents/common.d.ts +1 -1
- package/out/runtime/agents/common.d.ts.map +1 -1
- package/out/runtime/agents/common.js +32 -9
- package/out/runtime/agents/common.js.map +1 -1
- package/out/runtime/integrations.d.ts +3 -0
- package/out/runtime/integrations.d.ts.map +1 -0
- package/out/runtime/integrations.js +72 -0
- package/out/runtime/integrations.js.map +1 -0
- package/out/runtime/interpreter.d.ts.map +1 -1
- package/out/runtime/interpreter.js +73 -32
- package/out/runtime/interpreter.js.map +1 -1
- package/out/runtime/jsmodules.js +1 -1
- package/out/runtime/loader.js +2 -2
- package/out/runtime/loader.js.map +1 -1
- package/out/runtime/module.d.ts +2 -0
- package/out/runtime/module.d.ts.map +1 -1
- package/out/runtime/module.js +13 -2
- package/out/runtime/module.js.map +1 -1
- package/out/runtime/resolvers/sqldb/database.js +1 -1
- package/out/runtime/resolvers/sqldb/database.js.map +1 -1
- package/out/runtime/resolvers/sqldb/dbutil.d.ts.map +1 -1
- package/out/runtime/resolvers/sqldb/dbutil.js +3 -2
- package/out/runtime/resolvers/sqldb/dbutil.js.map +1 -1
- package/out/runtime/state.d.ts +28 -0
- package/out/runtime/state.d.ts.map +1 -1
- package/out/runtime/state.js +8 -0
- package/out/runtime/state.js.map +1 -1
- package/out/syntaxes/agentlang.monarch.js +1 -1
- package/out/syntaxes/agentlang.monarch.js.map +1 -1
- package/package.json +3 -3
- package/src/cli/main.ts +10 -0
- package/src/language/agentlang.langium +14 -10
- package/src/language/generated/ast.ts +43 -13
- package/src/language/generated/grammar.ts +231 -122
- package/src/runtime/agents/common.ts +32 -9
- package/src/runtime/integrations.ts +92 -0
- package/src/runtime/interpreter.ts +97 -35
- package/src/runtime/loader.ts +2 -2
- package/src/runtime/module.ts +15 -2
- package/src/runtime/resolvers/sqldb/database.ts +1 -1
- package/src/runtime/resolvers/sqldb/dbutil.ts +3 -2
- package/src/runtime/state.ts +8 -0
- package/src/syntaxes/agentlang.monarch.ts +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export const PlannerInstructions = `Agentlang is a very-high-level declarative language that makes it easy to define business applications as 'models'.
|
|
2
2
|
The model of a business application consists of entity definitions and workflows defined in "modules".
|
|
3
|
-
A module
|
|
3
|
+
A module is be encoded in a syntax inspired by JavaScript and JSON. Example of a simple module follows:
|
|
4
4
|
|
|
5
5
|
module Erp
|
|
6
6
|
|
|
@@ -12,9 +12,10 @@ entity Employee {
|
|
|
12
12
|
email Email @indexed
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
The Empoyee entity is part of the "Erp" module and it has four attributes: employeeId, firstName, lastName, salary and email.
|
|
16
|
-
Employee and it's automatically filled-in by the system by calling the "uuid()" function.
|
|
17
|
-
|
|
15
|
+
The Empoyee entity is part of the "Erp" module and it has four attributes: 'employeeId', 'firstName', 'lastName', 'salary' and 'email'.
|
|
16
|
+
The 'employeeId' attribute uniquely identifies an instance of the Employee entity and it's automatically filled-in by the system by calling the "uuid()" function.
|
|
17
|
+
In the place of the keyword 'entity', the keyword 'record' may also be used. The difference between an entity and a record is that,
|
|
18
|
+
instances of an entity is persisted to the database, instances of records are not.
|
|
18
19
|
|
|
19
20
|
This is an example of a record:
|
|
20
21
|
|
|
@@ -25,7 +26,8 @@ record EmailMessage {
|
|
|
25
26
|
body String
|
|
26
27
|
}
|
|
27
28
|
|
|
28
|
-
Workflows contains JSON "patterns" that perform CRUD operations on entities.
|
|
29
|
+
Another major construct in Agentlang is the 'workflow'. Workflows contains JSON "patterns" that perform CRUD operations on entities.
|
|
30
|
+
For example, here's is a workflow that creates a new instance of the Employee entity:
|
|
29
31
|
|
|
30
32
|
workflow CreateEmployee {
|
|
31
33
|
{Erp/Employee {firstName CreateEmployee.firstName,
|
|
@@ -49,7 +51,7 @@ A workflow attached to an event is invoked by creating an instance of the event,
|
|
|
49
51
|
|
|
50
52
|
{Erp/CreateEmployee {firstName "Sam", lastName "K", salary 1400, email "samk@acme.com"}}
|
|
51
53
|
|
|
52
|
-
This means a workflow can be invoked from another workflow, simply by
|
|
54
|
+
This means a workflow can be invoked from another workflow, simply by having the event-creation pattern.
|
|
53
55
|
|
|
54
56
|
Other than the create-pattern for entities and events, some of the most useful patterns (related to entities) that can appear in a workflow are:
|
|
55
57
|
1. Query - e.g: '{Erp/Employee {employeeId? "56392e13-0d9a-42f7-b556-0d7cd9468a24"}}'. The attributes by which the query happens must end with a '?' character.
|
|
@@ -58,7 +60,7 @@ Other than the create-pattern for entities and events, some of the most useful p
|
|
|
58
60
|
with the given employeeId.
|
|
59
61
|
3. Upsert - e.g: '{Erp/Employee {employeeId "56392e13-0d9a-42f7-b556-0d7cd9468a24", firstName "Joe"}, @upsert}'. The 'upsert' pattern will create a new
|
|
60
62
|
instance, if the instance does not already exist.
|
|
61
|
-
4. Delete - e.g: delete
|
|
63
|
+
4. Delete - e.g: 'delete {Erp/Employee {employeeId? "56392e13-0d9a-42f7-b556-0d7cd9468a24"}}'
|
|
62
64
|
|
|
63
65
|
The default query operator is '=' (equals). So an expression like 'employeeId? "56392e13-0d9a-42f7-b556-0d7cd9468a24"' means,
|
|
64
66
|
'where employeeId equals "56392e13-0d9a-42f7-b556-0d7cd9468a24"'. Other comparison operators has to be specified explicitly, as in
|
|
@@ -89,6 +91,19 @@ workflow IncrementSalary {
|
|
|
89
91
|
|
|
90
92
|
Note the value passed to the 'salary' attribute - it's an arithmetic expression. All normal arithmetic expressions are supported by workflow patterns.
|
|
91
93
|
|
|
94
|
+
Another example of the 'if' pattern:
|
|
95
|
+
|
|
96
|
+
workflow validateLicense {
|
|
97
|
+
{checkLicenseNumber {number validateLicense.number}} @as response;
|
|
98
|
+
if (response = "ok") {
|
|
99
|
+
{license {number? validateLicense.number, status "active"}}
|
|
100
|
+
} else {
|
|
101
|
+
{license {number? validateLicense.number, status "canceled"}}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
Also note the use of the '@as' keyword - this binds the result of a pattern to an 'alias'.
|
|
106
|
+
|
|
92
107
|
A successful query pattern will return an array of instances. The 'for' pattern can be used to iterate over an array. An example follows:
|
|
93
108
|
|
|
94
109
|
workflow NotifyEmployees {
|
|
@@ -98,8 +113,7 @@ workflow NotifyEmployees {
|
|
|
98
113
|
}
|
|
99
114
|
}
|
|
100
115
|
|
|
101
|
-
|
|
102
|
-
alias named 'employees'. Any pattern can have an alias, including 'if' and 'for'. An alias can be used to refer to the attributes of the instance,
|
|
116
|
+
Here the result of the query is bound to the alias named 'employees'. Any pattern can have an alias, including 'if' and 'for'. An alias can be used to refer to the attributes of the instance,
|
|
103
117
|
via the dot(.) notation. Aliases can also be used to destructure a query result - here's an example:
|
|
104
118
|
|
|
105
119
|
workflow FindFirstTwoEmployees {
|
|
@@ -134,6 +148,15 @@ A fix for the reference-error is shown below:
|
|
|
134
148
|
{Employee {id? 101}} @as employee;
|
|
135
149
|
{SendEmail {to employee.email, body "hello"}}
|
|
136
150
|
|
|
151
|
+
A pattern may execute asynchronously and its eventual result can be handled by patterns provided in the '@then' clause. An example is shown below:
|
|
152
|
+
|
|
153
|
+
{sendChatMessage {to "amy", "text" "hello"}} @as response @then {
|
|
154
|
+
{saveResponse {from "amy", "text" response}}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
If you are instructed that a particular event will be called asynchronously, always provide the patterns that follows in its '@then' clause. You must add the
|
|
158
|
+
'@then' clause only if an event's documentation or instruction explicitly requires to do so.
|
|
159
|
+
|
|
137
160
|
Entities in a module can be connected together in relationships. There are two types of relationships - 'contains' and 'between'.
|
|
138
161
|
'Contains' relationship is for hierarchical data, as in a Library entity containing Books. 'Between' relationship is for graph-like data,
|
|
139
162
|
like two Profiles in a social media app is connected as friends. A 'between' relationship can be one of the following three types - 'one_one' (one-to-one),
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { Instance } from './module.js';
|
|
2
|
+
import { isString } from './util.js';
|
|
3
|
+
|
|
4
|
+
const Integrations = new Map<string, Instance>();
|
|
5
|
+
|
|
6
|
+
const IntegManagerModel = 'integmanager.core';
|
|
7
|
+
|
|
8
|
+
export async function prepareIntegrations(
|
|
9
|
+
integManagerHost: string,
|
|
10
|
+
username: string | undefined,
|
|
11
|
+
password: string | undefined,
|
|
12
|
+
integConfigObj: object
|
|
13
|
+
) {
|
|
14
|
+
const integConfig = new Map(Object.entries(integConfigObj));
|
|
15
|
+
const standardHeaders = await loginToIntegManager(integManagerHost, username, password);
|
|
16
|
+
const keys = [...integConfig.keys()];
|
|
17
|
+
for (let i = 0; i < keys.length; ++i) {
|
|
18
|
+
const configName = keys[i];
|
|
19
|
+
const configPath = integConfig.get(configName);
|
|
20
|
+
if (configPath) {
|
|
21
|
+
const apiUrl = mkApiUrl(integManagerHost, configPath);
|
|
22
|
+
const response = await fetch(apiUrl, {
|
|
23
|
+
method: 'GET',
|
|
24
|
+
headers: standardHeaders,
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
if (!response.ok) {
|
|
28
|
+
throw new Error(
|
|
29
|
+
`Failed to fetch integration for ${configPath}, HTTP error! status: ${response.status} ${response.text} ${response.statusText}`
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const data = await response.json();
|
|
34
|
+
if (data.length > 0) {
|
|
35
|
+
const inst: any = data[0].config;
|
|
36
|
+
if (inst.type == 'custom' && isString(inst.parameter)) {
|
|
37
|
+
inst.parameter = new Map(Object.entries(JSON.parse(inst.parameter)));
|
|
38
|
+
}
|
|
39
|
+
Integrations.set(configName, inst);
|
|
40
|
+
} else {
|
|
41
|
+
throw new Error(`Integration not found for ${configPath}`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async function loginToIntegManager(
|
|
48
|
+
host: string,
|
|
49
|
+
username?: string,
|
|
50
|
+
password?: string
|
|
51
|
+
): Promise<any> {
|
|
52
|
+
const defaultHdr = { 'Content-Type': 'application/json' };
|
|
53
|
+
if (username && password && username.length > 0) {
|
|
54
|
+
const apiUrl = `${host}/agentlang_auth/login`;
|
|
55
|
+
const data = { email: username, password: password };
|
|
56
|
+
const response = await fetch(apiUrl, {
|
|
57
|
+
method: 'POST',
|
|
58
|
+
headers: defaultHdr,
|
|
59
|
+
body: JSON.stringify(data),
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
if (!response.ok) {
|
|
63
|
+
throw new Error(
|
|
64
|
+
`Failed to login to integration-manager. HTTP error! status: ${response.status}`
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const responseData = await response.json();
|
|
69
|
+
return {
|
|
70
|
+
Authorization: `Bearer ${responseData.id_token}`,
|
|
71
|
+
'Content-Type': 'application/json',
|
|
72
|
+
};
|
|
73
|
+
} else {
|
|
74
|
+
return defaultHdr;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function mkApiUrl(integManagerHost: string, configPath: string): string {
|
|
79
|
+
const parts = configPath.split('/');
|
|
80
|
+
const integId = parts[0];
|
|
81
|
+
const configId = parts[1];
|
|
82
|
+
return `${integManagerHost}/${IntegManagerModel}/integration/${integId}/integrationConfig/config/${configId}`;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export function getIntegrationConfig(name: string, configName: string): any {
|
|
86
|
+
const config: any = Integrations.get(name);
|
|
87
|
+
if (config) {
|
|
88
|
+
return config.parameter.get(configName);
|
|
89
|
+
} else {
|
|
90
|
+
return undefined;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
isLiteral,
|
|
14
14
|
isNegExpr,
|
|
15
15
|
isNotExpr,
|
|
16
|
+
isReturn,
|
|
16
17
|
Literal,
|
|
17
18
|
MapKey,
|
|
18
19
|
MapLiteral,
|
|
@@ -607,27 +608,28 @@ function statemtentString(stmt: Statement): string {
|
|
|
607
608
|
}
|
|
608
609
|
}
|
|
609
610
|
|
|
611
|
+
async function saveSuspension(cont: Statement[], env: Environment) {
|
|
612
|
+
if (cont.length > 0) {
|
|
613
|
+
const suspId = await createSuspension(
|
|
614
|
+
env.getSuspensionId(),
|
|
615
|
+
cont.map((stmt: Statement) => {
|
|
616
|
+
return statemtentString(stmt);
|
|
617
|
+
}),
|
|
618
|
+
env
|
|
619
|
+
);
|
|
620
|
+
env.setLastResult({ suspension: suspId || 'null' });
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
|
|
610
624
|
export async function evaluateStatements(
|
|
611
625
|
stmts: Statement[],
|
|
612
626
|
env: Environment,
|
|
613
627
|
continuation?: Function
|
|
614
628
|
) {
|
|
615
629
|
for (let i = 0; i < stmts.length; ++i) {
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
if (cont.length > 0) {
|
|
620
|
-
const suspId = await createSuspension(
|
|
621
|
-
env.getSuspensionId(),
|
|
622
|
-
cont.map((stmt: Statement) => {
|
|
623
|
-
return statemtentString(stmt);
|
|
624
|
-
}),
|
|
625
|
-
env
|
|
626
|
-
);
|
|
627
|
-
env.setLastResult({ suspension: suspId || 'null' });
|
|
628
|
-
break;
|
|
629
|
-
}
|
|
630
|
-
} else if (env.isMarkedForReturn()) {
|
|
630
|
+
const stmt = stmts[i];
|
|
631
|
+
await evaluateStatement(stmt, env);
|
|
632
|
+
if (env.isMarkedForReturn()) {
|
|
631
633
|
break;
|
|
632
634
|
}
|
|
633
635
|
}
|
|
@@ -636,10 +638,44 @@ export async function evaluateStatements(
|
|
|
636
638
|
}
|
|
637
639
|
}
|
|
638
640
|
|
|
641
|
+
async function evaluateAsyncPattern(
|
|
642
|
+
pat: Pattern,
|
|
643
|
+
thenStmts: Statement[],
|
|
644
|
+
handlers: CatchHandlers | undefined,
|
|
645
|
+
hints: RuntimeHint[],
|
|
646
|
+
env: Environment
|
|
647
|
+
): Promise<void> {
|
|
648
|
+
try {
|
|
649
|
+
await evaluatePattern(pat, env);
|
|
650
|
+
maybeBindStatementResultToAlias(hints, env);
|
|
651
|
+
if (env.isSuspended()) {
|
|
652
|
+
await saveSuspension(thenStmts, env);
|
|
653
|
+
} else {
|
|
654
|
+
await evaluateStatements(thenStmts, env);
|
|
655
|
+
}
|
|
656
|
+
} catch (reason: any) {
|
|
657
|
+
await maybeHandleError(handlers, reason, env);
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
|
|
639
661
|
async function evaluateStatement(stmt: Statement, env: Environment): Promise<void> {
|
|
640
662
|
const hints = stmt.hints;
|
|
641
663
|
const hasHints = hints && hints.length > 0;
|
|
664
|
+
const thenStmts: Statement[] | undefined = hasHints ? maybeFindThenStatements(hints) : undefined;
|
|
642
665
|
const handlers: CatchHandlers | undefined = hasHints ? maybeFindHandlers(hints) : undefined;
|
|
666
|
+
if (thenStmts) {
|
|
667
|
+
evaluateAsyncPattern(
|
|
668
|
+
stmt.pattern,
|
|
669
|
+
thenStmts,
|
|
670
|
+
handlers,
|
|
671
|
+
hints,
|
|
672
|
+
new Environment(env.name + 'async', env)
|
|
673
|
+
);
|
|
674
|
+
if (isReturn(stmt.pattern)) {
|
|
675
|
+
env.markForReturn();
|
|
676
|
+
}
|
|
677
|
+
return;
|
|
678
|
+
}
|
|
643
679
|
let handlersPushed = false;
|
|
644
680
|
try {
|
|
645
681
|
if (handlers) {
|
|
@@ -649,24 +685,9 @@ async function evaluateStatement(stmt: Statement, env: Environment): Promise<voi
|
|
|
649
685
|
if (hasHints) {
|
|
650
686
|
maybeBindStatementResultToAlias(hints, env);
|
|
651
687
|
}
|
|
652
|
-
|
|
653
|
-
if (
|
|
654
|
-
lastResult == null ||
|
|
655
|
-
lastResult == undefined ||
|
|
656
|
-
(lastResult instanceof Array && lastResult.length == 0)
|
|
657
|
-
) {
|
|
658
|
-
const onNotFound = handlers ? handlers.get('not_found') : undefined;
|
|
659
|
-
if (onNotFound) {
|
|
660
|
-
await evaluateStatement(onNotFound, env);
|
|
661
|
-
}
|
|
662
|
-
}
|
|
688
|
+
await maybeHandleNotFound(handlers, env);
|
|
663
689
|
} catch (reason: any) {
|
|
664
|
-
|
|
665
|
-
if (handler) {
|
|
666
|
-
await evaluateStatement(handler, env);
|
|
667
|
-
} else {
|
|
668
|
-
throw reason;
|
|
669
|
-
}
|
|
690
|
+
await maybeHandleError(handlers, reason, env);
|
|
670
691
|
} finally {
|
|
671
692
|
if (handlersPushed && env.hasHandlers()) {
|
|
672
693
|
env.popHandlers();
|
|
@@ -674,6 +695,33 @@ async function evaluateStatement(stmt: Statement, env: Environment): Promise<voi
|
|
|
674
695
|
}
|
|
675
696
|
}
|
|
676
697
|
|
|
698
|
+
async function maybeHandleNotFound(handlers: CatchHandlers | undefined, env: Environment) {
|
|
699
|
+
const lastResult: Result = env.getLastResult();
|
|
700
|
+
if (
|
|
701
|
+
lastResult == null ||
|
|
702
|
+
lastResult == undefined ||
|
|
703
|
+
(lastResult instanceof Array && lastResult.length == 0)
|
|
704
|
+
) {
|
|
705
|
+
const onNotFound = handlers ? handlers.get('not_found') : undefined;
|
|
706
|
+
if (onNotFound) {
|
|
707
|
+
await evaluateStatement(onNotFound, env);
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
async function maybeHandleError(
|
|
713
|
+
handlers: CatchHandlers | undefined,
|
|
714
|
+
reason: any,
|
|
715
|
+
env: Environment
|
|
716
|
+
) {
|
|
717
|
+
const handler = handlers ? handlers.get('error') : undefined;
|
|
718
|
+
if (handler) {
|
|
719
|
+
await evaluateStatement(handler, env);
|
|
720
|
+
} else {
|
|
721
|
+
throw reason;
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
|
|
677
725
|
function maybeBindStatementResultToAlias(hints: RuntimeHint[], env: Environment) {
|
|
678
726
|
for (let i = 0; i < hints.length; ++i) {
|
|
679
727
|
const rh = hints[i];
|
|
@@ -720,6 +768,16 @@ function maybeFindHandlers(hints: RuntimeHint[]): Map<string, Statement> | undef
|
|
|
720
768
|
return undefined;
|
|
721
769
|
}
|
|
722
770
|
|
|
771
|
+
function maybeFindThenStatements(hints: RuntimeHint[]): Statement[] | undefined {
|
|
772
|
+
for (let i = 0; i < hints.length; ++i) {
|
|
773
|
+
const rh = hints[i];
|
|
774
|
+
if (rh.thenSpec) {
|
|
775
|
+
return rh.thenSpec.statements;
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
return undefined;
|
|
779
|
+
}
|
|
780
|
+
|
|
723
781
|
export async function parseAndEvaluateStatement(
|
|
724
782
|
stmtString: string,
|
|
725
783
|
activeUserId?: string,
|
|
@@ -1237,9 +1295,11 @@ async function walkJoinQueryPattern(
|
|
|
1237
1295
|
async function handleAgentInvocation(agentEventInst: Instance, env: Environment): Promise<void> {
|
|
1238
1296
|
const agent: AgentInstance = await findAgentByName(agentEventInst.name, env);
|
|
1239
1297
|
await agent.invoke(agentEventInst.lookup('message'), env);
|
|
1240
|
-
const
|
|
1298
|
+
const r: string | undefined = env.getLastResult();
|
|
1299
|
+
const isPlanner = agent.isPlanner();
|
|
1300
|
+
const result: string | undefined = isPlanner ? cleanupAgentResponse(r) : r;
|
|
1241
1301
|
if (result) {
|
|
1242
|
-
if (
|
|
1302
|
+
if (isPlanner) {
|
|
1243
1303
|
logger.debug(`Agent ${agent.name} generated pattern: ${result}`);
|
|
1244
1304
|
try {
|
|
1245
1305
|
let rs = result.trim();
|
|
@@ -1310,11 +1370,13 @@ async function evaluateForEach(forEach: ForEach, env: Environment): Promise<void
|
|
|
1310
1370
|
const src: Result = env.getLastResult();
|
|
1311
1371
|
if (src instanceof Array && src.length > 0) {
|
|
1312
1372
|
const loopEnv: Environment = Environment.from(env);
|
|
1373
|
+
const finalResult = new Array<any>();
|
|
1313
1374
|
for (let i = 0; i < src.length; ++i) {
|
|
1314
1375
|
loopEnv.bind(loopVar, src[i]);
|
|
1315
1376
|
await evaluateStatements(forEach.statements, loopEnv);
|
|
1377
|
+
finalResult.push(loopEnv.getLastResult());
|
|
1316
1378
|
}
|
|
1317
|
-
env.setLastResult(
|
|
1379
|
+
env.setLastResult(finalResult);
|
|
1318
1380
|
} else {
|
|
1319
1381
|
env.setLastResult(EmptyResult);
|
|
1320
1382
|
}
|
package/src/runtime/loader.ts
CHANGED
|
@@ -421,7 +421,7 @@ async function addAgentDefinition(def: AgentDefinition, moduleName: string) {
|
|
|
421
421
|
v = apdef.value.array.vals
|
|
422
422
|
.map((stmt: Statement) => {
|
|
423
423
|
if (stmt.pattern.expr && isLiteral(stmt.pattern.expr)) {
|
|
424
|
-
const s = stmt.pattern.expr.str || stmt.pattern.expr.id;
|
|
424
|
+
const s = stmt.pattern.expr.str || stmt.pattern.expr.id || stmt.pattern.expr.ref;
|
|
425
425
|
if (s == undefined) {
|
|
426
426
|
throw new Error(
|
|
427
427
|
`Only arrays of string-literals or identifiers should be passed to agent ${name}`
|
|
@@ -434,7 +434,7 @@ async function addAgentDefinition(def: AgentDefinition, moduleName: string) {
|
|
|
434
434
|
})
|
|
435
435
|
.join(',');
|
|
436
436
|
} else {
|
|
437
|
-
v = apdef.value.str || apdef.value.id || apdef.value.num;
|
|
437
|
+
v = apdef.value.str || apdef.value.id || apdef.value.ref || apdef.value.num;
|
|
438
438
|
if (v == undefined) {
|
|
439
439
|
v = apdef.value.bool;
|
|
440
440
|
}
|
package/src/runtime/module.ts
CHANGED
|
@@ -2206,14 +2206,27 @@ export class Instance {
|
|
|
2206
2206
|
return obj;
|
|
2207
2207
|
}
|
|
2208
2208
|
|
|
2209
|
+
static isSerializableObject(obj: any): boolean {
|
|
2210
|
+
return obj instanceof Object && obj.AL_INSTANCE == true;
|
|
2211
|
+
}
|
|
2212
|
+
|
|
2213
|
+
static DeserializeAttributes(attrs: InstanceAttributes): InstanceAttributes {
|
|
2214
|
+
attrs.forEach((v: any, k: string) => {
|
|
2215
|
+
if (Instance.isSerializableObject(v)) {
|
|
2216
|
+
attrs.set(k, Instance.FromSerializableObject(v));
|
|
2217
|
+
}
|
|
2218
|
+
});
|
|
2219
|
+
return attrs;
|
|
2220
|
+
}
|
|
2221
|
+
|
|
2209
2222
|
static FromSerializableObject(obj: any, record?: Record): Instance {
|
|
2210
|
-
if (obj
|
|
2223
|
+
if (Instance.isSerializableObject(obj)) {
|
|
2211
2224
|
const m = fetchModule(obj.moduleName);
|
|
2212
2225
|
return new Instance(
|
|
2213
2226
|
record || (m.getEntry(obj.name) as Record),
|
|
2214
2227
|
obj.moduleName,
|
|
2215
2228
|
obj.name,
|
|
2216
|
-
new Map(Object.entries(obj.attributes)),
|
|
2229
|
+
Instance.DeserializeAttributes(new Map(Object.entries(obj.attributes))),
|
|
2217
2230
|
new Map(Object.entries(obj.queryAttributes)),
|
|
2218
2231
|
new Map(Object.entries(obj.queryAttributeValues))
|
|
2219
2232
|
);
|
|
@@ -239,7 +239,7 @@ export async function resetDefaultDatabase() {
|
|
|
239
239
|
}
|
|
240
240
|
|
|
241
241
|
function ownersTable(tableName: string): string {
|
|
242
|
-
return (tableName + OwnersSuffix).toLowerCase();
|
|
242
|
+
return (tableName.replace('.', '_') + OwnersSuffix).toLowerCase();
|
|
243
243
|
}
|
|
244
244
|
|
|
245
245
|
async function insertRowsHelper(
|
|
@@ -31,13 +31,14 @@ export type TableSchema = {
|
|
|
31
31
|
};
|
|
32
32
|
|
|
33
33
|
export function asTableReference(moduleName: string, ref: string): string {
|
|
34
|
+
const modName = moduleName.replace('.', '_')
|
|
34
35
|
if (ref.indexOf('.') > 0) {
|
|
35
36
|
const parts = ref.split('.')
|
|
36
|
-
const r = `${
|
|
37
|
+
const r = `${modName}_${parts[0]}`.toLowerCase()
|
|
37
38
|
const colref = parts.slice(1).join('.')
|
|
38
39
|
return `"${r}"."${colref}"`;
|
|
39
40
|
} else {
|
|
40
|
-
return `${
|
|
41
|
+
return `${modName}_${ref}`.toLowerCase()
|
|
41
42
|
}
|
|
42
43
|
}
|
|
43
44
|
|
package/src/runtime/state.ts
CHANGED
|
@@ -33,6 +33,14 @@ export const ConfigSchema = z.object({
|
|
|
33
33
|
}),
|
|
34
34
|
])
|
|
35
35
|
.optional(),
|
|
36
|
+
integrations: z
|
|
37
|
+
.object({
|
|
38
|
+
host: z.string(),
|
|
39
|
+
username: z.string().optional(),
|
|
40
|
+
password: z.string().optional(),
|
|
41
|
+
connections: z.record(z.string(), z.string()),
|
|
42
|
+
})
|
|
43
|
+
.optional(),
|
|
36
44
|
graphql: z
|
|
37
45
|
.object({
|
|
38
46
|
enabled: z.boolean().default(false),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Monarch syntax highlighting for the agentlang language.
|
|
2
2
|
export default {
|
|
3
3
|
keywords: [
|
|
4
|
-
'@actions','@after','@as','@async','@before','@catch','@distinct','@enum','@expr','@from','@into','@meta','@oneof','@rbac','@ref','@upsert','@with_unique','agent','allow','and','await','between','contains','create','delete','else','entity','error','event','extends','false','for','if','import','in','like','module','not','not_found','onSubscription','or','purge','query','read','record','relationship','resolver','return','roles','subscribe','true','update','upsert','where','workflow'
|
|
4
|
+
'@actions','@after','@as','@async','@before','@catch','@distinct','@enum','@expr','@from','@into','@meta','@oneof','@rbac','@ref','@then','@upsert','@with_unique','agent','allow','and','await','between','contains','create','delete','else','entity','error','event','extends','false','for','if','import','in','like','module','not','not_found','onSubscription','or','purge','query','read','record','relationship','resolver','return','roles','subscribe','true','update','upsert','where','workflow'
|
|
5
5
|
],
|
|
6
6
|
operators: [
|
|
7
7
|
'*','+',',','-','.','/',':',';','<','<=','<>','=','>','>=','?','@'
|