agentlang 0.0.3 → 0.0.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 +16 -47
- package/out/api/http.d.ts.map +1 -1
- package/out/api/http.js +39 -19
- package/out/api/http.js.map +1 -1
- package/out/cli/main.d.ts +1 -3
- package/out/cli/main.d.ts.map +1 -1
- package/out/cli/main.js +6 -12
- package/out/cli/main.js.map +1 -1
- package/out/language/generated/ast.d.ts +98 -19
- package/out/language/generated/ast.d.ts.map +1 -1
- package/out/language/generated/ast.js +144 -26
- 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 +1000 -305
- 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 +1097 -312
- package/out/language/main.cjs.map +2 -2
- package/out/language/parser.js +13 -6
- package/out/language/parser.js.map +1 -1
- 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 +1 -1
- package/out/runtime/auth/cognito.d.ts +4 -1
- package/out/runtime/auth/cognito.d.ts.map +1 -1
- package/out/runtime/auth/cognito.js +540 -73
- package/out/runtime/auth/cognito.js.map +1 -1
- package/out/runtime/auth/defs.d.ts +3 -0
- package/out/runtime/auth/defs.d.ts.map +1 -1
- package/out/runtime/auth/defs.js +17 -1
- package/out/runtime/auth/defs.js.map +1 -1
- package/out/runtime/auth/interface.d.ts +6 -1
- package/out/runtime/auth/interface.d.ts.map +1 -1
- package/out/runtime/defs.d.ts +21 -0
- package/out/runtime/defs.d.ts.map +1 -1
- package/out/runtime/defs.js +35 -0
- package/out/runtime/defs.js.map +1 -1
- package/out/runtime/interpreter.d.ts.map +1 -1
- package/out/runtime/interpreter.js +45 -36
- package/out/runtime/interpreter.js.map +1 -1
- package/out/runtime/loader.d.ts +4 -2
- package/out/runtime/loader.d.ts.map +1 -1
- package/out/runtime/loader.js +164 -29
- package/out/runtime/loader.js.map +1 -1
- package/out/runtime/module.d.ts +49 -5
- package/out/runtime/module.d.ts.map +1 -1
- package/out/runtime/module.js +214 -9
- package/out/runtime/module.js.map +1 -1
- package/out/runtime/modules/ai.d.ts +7 -5
- package/out/runtime/modules/ai.d.ts.map +1 -1
- package/out/runtime/modules/ai.js +50 -24
- package/out/runtime/modules/ai.js.map +1 -1
- package/out/runtime/modules/auth.d.ts +17 -1
- package/out/runtime/modules/auth.d.ts.map +1 -1
- package/out/runtime/modules/auth.js +295 -32
- 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 -1
- package/out/runtime/modules/core.js.map +1 -1
- package/out/runtime/relgraph.d.ts.map +1 -1
- package/out/runtime/relgraph.js +2 -2
- package/out/runtime/relgraph.js.map +1 -1
- package/out/runtime/resolvers/interface.d.ts +37 -2
- package/out/runtime/resolvers/interface.d.ts.map +1 -1
- package/out/runtime/resolvers/interface.js +103 -5
- package/out/runtime/resolvers/interface.js.map +1 -1
- package/out/runtime/resolvers/registry.d.ts +3 -2
- package/out/runtime/resolvers/registry.d.ts.map +1 -1
- package/out/runtime/resolvers/registry.js +3 -0
- package/out/runtime/resolvers/registry.js.map +1 -1
- package/out/runtime/resolvers/sqldb/database.d.ts +4 -2
- package/out/runtime/resolvers/sqldb/database.d.ts.map +1 -1
- package/out/runtime/resolvers/sqldb/database.js +43 -4
- package/out/runtime/resolvers/sqldb/database.js.map +1 -1
- package/out/runtime/resolvers/sqldb/impl.d.ts.map +1 -1
- package/out/runtime/resolvers/sqldb/impl.js +7 -3
- package/out/runtime/resolvers/sqldb/impl.js.map +1 -1
- package/out/runtime/state.d.ts +31 -3
- package/out/runtime/state.d.ts.map +1 -1
- package/out/runtime/state.js +11 -1
- package/out/runtime/state.js.map +1 -1
- package/out/runtime/util.d.ts +5 -0
- package/out/runtime/util.d.ts.map +1 -1
- package/out/runtime/util.js +27 -0
- package/out/runtime/util.js.map +1 -1
- package/out/syntaxes/agentlang.monarch.js +2 -2
- package/out/syntaxes/agentlang.monarch.js.map +1 -1
- package/out/utils/http.d.ts +2 -0
- package/out/utils/http.d.ts.map +1 -0
- package/out/utils/http.js +5 -0
- package/out/utils/http.js.map +1 -0
- package/package.json +8 -6
- package/src/api/http.ts +41 -17
- package/src/cli/main.ts +6 -12
- package/src/language/agentlang.langium +35 -10
- package/src/language/generated/ast.ts +257 -45
- package/src/language/generated/grammar.ts +1000 -305
- package/src/language/generated/module.ts +1 -1
- package/src/language/parser.ts +12 -8
- package/src/runtime/agents/common.ts +1 -1
- package/src/runtime/auth/cognito.ts +605 -74
- package/src/runtime/auth/defs.ts +17 -1
- package/src/runtime/auth/interface.ts +6 -1
- package/src/runtime/defs.ts +45 -0
- package/src/runtime/interpreter.ts +43 -34
- package/src/runtime/loader.ts +172 -30
- package/src/runtime/module.ts +257 -10
- package/src/runtime/modules/ai.ts +52 -28
- package/src/runtime/modules/auth.ts +343 -40
- package/src/runtime/modules/core.ts +3 -1
- package/src/runtime/relgraph.ts +2 -8
- package/src/runtime/resolvers/interface.ts +141 -6
- package/src/runtime/resolvers/registry.ts +5 -2
- package/src/runtime/resolvers/sqldb/database.ts +55 -4
- package/src/runtime/resolvers/sqldb/impl.ts +8 -7
- package/src/runtime/state.ts +11 -1
- package/src/runtime/util.ts +29 -0
- package/src/syntaxes/agentlang.monarch.ts +2 -2
- package/src/utils/http.ts +5 -0
- package/src/index.ts +0 -29
package/src/runtime/auth/defs.ts
CHANGED
|
@@ -4,13 +4,29 @@ import { AppConfig } from '../state.js';
|
|
|
4
4
|
export const AdminUserId = '00000000-0000-0000-0000-000000000000';
|
|
5
5
|
|
|
6
6
|
export function isAuthEnabled(): boolean {
|
|
7
|
-
if (AppConfig
|
|
7
|
+
if (AppConfig?.auth?.enabled == true) {
|
|
8
8
|
return true;
|
|
9
9
|
} else {
|
|
10
10
|
return false;
|
|
11
11
|
}
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
export let InternalRbacEnabled = false;
|
|
15
|
+
|
|
16
|
+
export function isRbacEnabled(): boolean {
|
|
17
|
+
return InternalRbacEnabled || (isAuthEnabled() && AppConfig?.rbac?.enabled == true);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export async function callWithRbac(f: Function): Promise<void> {
|
|
21
|
+
const old = InternalRbacEnabled;
|
|
22
|
+
InternalRbacEnabled = true;
|
|
23
|
+
try {
|
|
24
|
+
await f();
|
|
25
|
+
} finally {
|
|
26
|
+
InternalRbacEnabled = old;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
14
30
|
export type ActiveSessionInfo = {
|
|
15
31
|
sessionId: string;
|
|
16
32
|
userId: string;
|
|
@@ -10,6 +10,9 @@ export type SessionInfo = {
|
|
|
10
10
|
sessionId: string; // a UUID
|
|
11
11
|
userId: string; // UUID
|
|
12
12
|
authToken: string;
|
|
13
|
+
idToken?: string;
|
|
14
|
+
accessToken?: string;
|
|
15
|
+
refreshToken?: string;
|
|
13
16
|
systemSesionInfo?: any;
|
|
14
17
|
};
|
|
15
18
|
|
|
@@ -27,5 +30,7 @@ export interface AgentlangAuth {
|
|
|
27
30
|
): any;
|
|
28
31
|
login(username: string, password: string, env: Environment, cb: LoginCallback): any;
|
|
29
32
|
logout(sessionInfo: SessionInfo, env: Environment, cb?: LogoutCallback): any;
|
|
30
|
-
verifyToken(token: string, env
|
|
33
|
+
verifyToken(token: string, env?: Environment): any;
|
|
34
|
+
getUser(userId: string, env: Environment): Promise<UserInfo>;
|
|
35
|
+
getUserByEmail(email: string, env: Environment): Promise<UserInfo>;
|
|
31
36
|
}
|
package/src/runtime/defs.ts
CHANGED
|
@@ -31,3 +31,48 @@ export class BadRequestError extends Error {
|
|
|
31
31
|
super(message ? asUnauthMessage(message) : 'BadRequest', options);
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
|
+
|
|
35
|
+
export class UserNotFoundError extends Error {
|
|
36
|
+
constructor(message?: string, options?: ErrorOptions) {
|
|
37
|
+
super(message || 'User not found', options);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export class UserNotConfirmedError extends Error {
|
|
42
|
+
constructor(message?: string, options?: ErrorOptions) {
|
|
43
|
+
super(
|
|
44
|
+
message || 'User account is not confirmed. Please check your email for verification code.',
|
|
45
|
+
options
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export class PasswordResetRequiredError extends Error {
|
|
51
|
+
constructor(message?: string, options?: ErrorOptions) {
|
|
52
|
+
super(message || 'Password reset is required for this account', options);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export class TooManyRequestsError extends Error {
|
|
57
|
+
constructor(message?: string, options?: ErrorOptions) {
|
|
58
|
+
super(message || 'Too many requests. Please try again later.', options);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export class InvalidParameterError extends Error {
|
|
63
|
+
constructor(message?: string, options?: ErrorOptions) {
|
|
64
|
+
super(message || 'Invalid parameters provided', options);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export class ExpiredCodeError extends Error {
|
|
69
|
+
constructor(message?: string, options?: ErrorOptions) {
|
|
70
|
+
super(message || 'The verification code has expired. Please request a new one.', options);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export class CodeMismatchError extends Error {
|
|
75
|
+
constructor(message?: string, options?: ErrorOptions) {
|
|
76
|
+
super(message || 'The verification code is incorrect. Please try again.', options);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -24,7 +24,6 @@ import {
|
|
|
24
24
|
SelectIntoSpec,
|
|
25
25
|
SetAttribute,
|
|
26
26
|
Statement,
|
|
27
|
-
Upsert,
|
|
28
27
|
} from '../language/generated/ast.js';
|
|
29
28
|
import {
|
|
30
29
|
defineAgentEvent,
|
|
@@ -33,7 +32,7 @@ import {
|
|
|
33
32
|
getWorkflow,
|
|
34
33
|
Instance,
|
|
35
34
|
InstanceAttributes,
|
|
36
|
-
|
|
35
|
+
isAgentEventInstance,
|
|
37
36
|
isBetweenRelationship,
|
|
38
37
|
isContainsRelationship,
|
|
39
38
|
isEmptyWorkflow,
|
|
@@ -62,13 +61,14 @@ import {
|
|
|
62
61
|
makeFqName,
|
|
63
62
|
Path,
|
|
64
63
|
QuerySuffix,
|
|
64
|
+
restoreSpecialChars,
|
|
65
65
|
splitFqName,
|
|
66
66
|
splitRefs,
|
|
67
67
|
} from './util.js';
|
|
68
68
|
import { getResolver, getResolverNameForPath } from './resolvers/registry.js';
|
|
69
69
|
import { parseStatement, parseWorkflow } from '../language/parser.js';
|
|
70
70
|
import { ActiveSessionInfo, AdminSession, AdminUserId } from './auth/defs.js';
|
|
71
|
-
import {
|
|
71
|
+
import { AgentInstance, AgentEntityName, AgentFqName, findAgentByName } from './modules/ai.js';
|
|
72
72
|
import { logger } from './logger.js';
|
|
73
73
|
import { ParentAttributeName, PathAttributeName, PathAttributeNameQuery } from './defs.js';
|
|
74
74
|
import {
|
|
@@ -602,8 +602,6 @@ async function evaluatePattern(pat: Pattern, env: Environment): Promise<void> {
|
|
|
602
602
|
await evaluateDelete(pat.delete, env);
|
|
603
603
|
} else if (pat.purge) {
|
|
604
604
|
await evaluatePurge(pat.purge, env);
|
|
605
|
-
} else if (pat.upsert) {
|
|
606
|
-
await evaluateUpsert(pat.upsert, env);
|
|
607
605
|
} else if (pat.fullTextSearch) {
|
|
608
606
|
await evaluateFullTextSearch(pat.fullTextSearch, env);
|
|
609
607
|
}
|
|
@@ -644,7 +642,7 @@ async function evaluateLiteral(lit: Literal, env: Environment): Promise<void> {
|
|
|
644
642
|
else if (lit.array != undefined) await realizeArray(lit.array, env);
|
|
645
643
|
else if (lit.map != undefined) await realizeMap(lit.map, env);
|
|
646
644
|
else if (lit.num != undefined) env.setLastResult(lit.num);
|
|
647
|
-
else if (lit.str != undefined) env.setLastResult(lit.str);
|
|
645
|
+
else if (lit.str != undefined) env.setLastResult(restoreSpecialChars(lit.str));
|
|
648
646
|
else if (lit.bool != undefined) env.setLastResult(lit.bool == 'true' ? true : false);
|
|
649
647
|
}
|
|
650
648
|
|
|
@@ -694,7 +692,7 @@ async function lookupOneOfVals(fqName: string, env: Environment): Promise<Instan
|
|
|
694
692
|
|
|
695
693
|
async function patternToInstance(
|
|
696
694
|
entryName: string,
|
|
697
|
-
attributes: SetAttribute[],
|
|
695
|
+
attributes: SetAttribute[] | undefined,
|
|
698
696
|
env: Environment
|
|
699
697
|
): Promise<Instance> {
|
|
700
698
|
const attrs: InstanceAttributes = newInstanceAttributes();
|
|
@@ -704,22 +702,24 @@ async function patternToInstance(
|
|
|
704
702
|
if (isQueryAll) {
|
|
705
703
|
entryName = entryName.slice(0, entryName.length - 1);
|
|
706
704
|
}
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
if (
|
|
714
|
-
|
|
705
|
+
if (attributes) {
|
|
706
|
+
for (let i = 0; i < attributes.length; ++i) {
|
|
707
|
+
const a: SetAttribute = attributes[i];
|
|
708
|
+
await evaluateExpression(a.value, env);
|
|
709
|
+
const v: Result = env.getLastResult();
|
|
710
|
+
let aname: string = a.name;
|
|
711
|
+
if (aname.endsWith(QuerySuffix)) {
|
|
712
|
+
if (isQueryAll) {
|
|
713
|
+
throw new Error(`Cannot specifiy query attribute ${aname} here`);
|
|
714
|
+
}
|
|
715
|
+
if (qattrs == undefined) qattrs = newInstanceAttributes();
|
|
716
|
+
if (qattrVals == undefined) qattrVals = newInstanceAttributes();
|
|
717
|
+
aname = aname.slice(0, aname.length - 1);
|
|
718
|
+
qattrs.set(aname, a.op == undefined ? '=' : a.op);
|
|
719
|
+
qattrVals.set(aname, v);
|
|
720
|
+
} else {
|
|
721
|
+
attrs.set(aname, v);
|
|
715
722
|
}
|
|
716
|
-
if (qattrs == undefined) qattrs = newInstanceAttributes();
|
|
717
|
-
if (qattrVals == undefined) qattrVals = newInstanceAttributes();
|
|
718
|
-
aname = aname.slice(0, aname.length - 1);
|
|
719
|
-
qattrs.set(aname, a.op == undefined ? '=' : a.op);
|
|
720
|
-
qattrVals.set(aname, v);
|
|
721
|
-
} else {
|
|
722
|
-
attrs.set(aname, v);
|
|
723
723
|
}
|
|
724
724
|
}
|
|
725
725
|
let moduleName = env.getActiveModuleName();
|
|
@@ -761,7 +761,10 @@ async function maybeValidateOneOfRefs(inst: Instance, env: Environment) {
|
|
|
761
761
|
}
|
|
762
762
|
|
|
763
763
|
async function evaluateCrudMap(crud: CrudMap, env: Environment): Promise<void> {
|
|
764
|
-
|
|
764
|
+
if (!env.isInUpsertMode() && crud.upsert) {
|
|
765
|
+
return await evaluateUpsert(crud, env);
|
|
766
|
+
}
|
|
767
|
+
const inst: Instance = await patternToInstance(crud.name, crud.body?.attributes, env);
|
|
765
768
|
const entryName = inst.name;
|
|
766
769
|
const moduleName = inst.moduleName;
|
|
767
770
|
const attrs = inst.attributes;
|
|
@@ -802,7 +805,7 @@ async function evaluateCrudMap(crud: CrudMap, env: Environment): Promise<void> {
|
|
|
802
805
|
r = await res.createInstance(inst);
|
|
803
806
|
await runPostCreateEvents(inst, env);
|
|
804
807
|
}
|
|
805
|
-
if (r && entryName ==
|
|
808
|
+
if (r && entryName == AgentEntityName) {
|
|
806
809
|
defineAgentEvent(env.getActiveModuleName(), r.lookup('name'));
|
|
807
810
|
}
|
|
808
811
|
env.setLastResult(r);
|
|
@@ -922,7 +925,7 @@ async function evaluateCrudMap(crud: CrudMap, env: Environment): Promise<void> {
|
|
|
922
925
|
}
|
|
923
926
|
}
|
|
924
927
|
} else if (isEventInstance(inst)) {
|
|
925
|
-
if (
|
|
928
|
+
if (isAgentEventInstance(inst)) await handleAgentInvocation(inst, env);
|
|
926
929
|
else await evaluate(inst, (result: Result) => env.setLastResult(result), env);
|
|
927
930
|
} else {
|
|
928
931
|
env.setLastResult(inst);
|
|
@@ -1029,7 +1032,7 @@ async function walkJoinQueryPattern(
|
|
|
1029
1032
|
await walkJoinQueryPattern(crudMap.relationships[i], subJoins, env);
|
|
1030
1033
|
}
|
|
1031
1034
|
}
|
|
1032
|
-
const qInst = await patternToInstance(crudMap.name, crudMap.attributes, env);
|
|
1035
|
+
const qInst = await patternToInstance(crudMap.name, crudMap.body?.attributes, env);
|
|
1033
1036
|
joinsSpec.push({
|
|
1034
1037
|
relationship: getRelationship(rp.name, qInst.moduleName),
|
|
1035
1038
|
queryInstance: qInst,
|
|
@@ -1042,24 +1045,30 @@ async function walkJoinQueryPattern(
|
|
|
1042
1045
|
}
|
|
1043
1046
|
|
|
1044
1047
|
async function handleAgentInvocation(agentEventInst: Instance, env: Environment): Promise<void> {
|
|
1045
|
-
const agent:
|
|
1048
|
+
const agent: AgentInstance = await findAgentByName(agentEventInst.name, env);
|
|
1046
1049
|
await agent.invoke(agentEventInst.lookup('message'), env);
|
|
1047
1050
|
const result: string = env.getLastResult();
|
|
1048
1051
|
if (agent.isPlanner()) {
|
|
1049
1052
|
logger.debug(`Agent ${agent.name} generated pattern: ${result}`);
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1053
|
+
try {
|
|
1054
|
+
if (result.trimStart().startsWith('workflow')) {
|
|
1055
|
+
await parseWorkflow(result);
|
|
1056
|
+
return;
|
|
1057
|
+
} else {
|
|
1058
|
+
env.setLastResult(await parseAndEvaluateStatement(result, undefined, env));
|
|
1059
|
+
}
|
|
1060
|
+
} catch (err: any) {
|
|
1061
|
+
logger.error(
|
|
1062
|
+
`Failed to evaluate pattern generated by agent ${agent.name} - ${result}, ${err}`
|
|
1063
|
+
);
|
|
1055
1064
|
}
|
|
1056
1065
|
}
|
|
1057
1066
|
}
|
|
1058
1067
|
|
|
1059
|
-
async function evaluateUpsert(
|
|
1068
|
+
async function evaluateUpsert(crud: CrudMap, env: Environment): Promise<void> {
|
|
1060
1069
|
env.setInUpsertMode(true);
|
|
1061
1070
|
try {
|
|
1062
|
-
await evaluateCrudMap(
|
|
1071
|
+
await evaluateCrudMap(crud, env);
|
|
1063
1072
|
} finally {
|
|
1064
1073
|
env.setInUpsertMode(false);
|
|
1065
1074
|
}
|
package/src/runtime/loader.ts
CHANGED
|
@@ -3,8 +3,6 @@ import { createAgentlangServices } from '../language/agentlang-module.js';
|
|
|
3
3
|
import {
|
|
4
4
|
Import,
|
|
5
5
|
RbacSpecEntries,
|
|
6
|
-
RbacSpecEntry,
|
|
7
|
-
RbacOpr,
|
|
8
6
|
ModuleDefinition,
|
|
9
7
|
Definition,
|
|
10
8
|
isEntityDefinition,
|
|
@@ -19,6 +17,12 @@ import {
|
|
|
19
17
|
Statement,
|
|
20
18
|
isStandaloneStatement,
|
|
21
19
|
SchemaDefinition,
|
|
20
|
+
isAgentDefinition,
|
|
21
|
+
AgentDefinition,
|
|
22
|
+
isResolverDefinition,
|
|
23
|
+
ResolverDefinition,
|
|
24
|
+
ResolverMethodSpec,
|
|
25
|
+
AgentPropertyDef,
|
|
22
26
|
} from '../language/generated/ast.js';
|
|
23
27
|
import {
|
|
24
28
|
addEntity,
|
|
@@ -36,10 +40,14 @@ import {
|
|
|
36
40
|
isModule,
|
|
37
41
|
getUserModuleNames,
|
|
38
42
|
removeModule,
|
|
43
|
+
newInstanceAttributes,
|
|
44
|
+
addAgent,
|
|
39
45
|
} from './module.js';
|
|
40
46
|
import {
|
|
41
47
|
findRbacSchema,
|
|
48
|
+
getModuleFn,
|
|
42
49
|
importModule,
|
|
50
|
+
isString,
|
|
43
51
|
makeFqName,
|
|
44
52
|
maybeExtends,
|
|
45
53
|
registerInitFunction,
|
|
@@ -51,10 +59,14 @@ import { URI } from 'vscode-uri';
|
|
|
51
59
|
import { AstNode, LangiumCoreServices, LangiumDocument } from 'langium';
|
|
52
60
|
import { isNodeEnv, path } from '../utils/runtime.js';
|
|
53
61
|
import { CoreModules, registerCoreModules } from './modules/core.js';
|
|
54
|
-
import { parse, parseModule } from '../language/parser.js';
|
|
62
|
+
import { parse, parseModule, parseWorkflow } from '../language/parser.js';
|
|
55
63
|
import { logger } from './logger.js';
|
|
56
64
|
import { Environment, evaluateStatements, GlobalEnvironment } from './interpreter.js';
|
|
57
65
|
import { createPermission, createRole } from './modules/auth.js';
|
|
66
|
+
import { AgentEntityName, CoreAIModuleName, LlmEntityName } from './modules/ai.js';
|
|
67
|
+
import { GenericResolver, GenericResolverMethods } from './resolvers/interface.js';
|
|
68
|
+
import { registerResolver, setResolver, setSubscription } from './resolvers/registry.js';
|
|
69
|
+
import { ConfigSchema } from './state.js';
|
|
58
70
|
|
|
59
71
|
export async function extractDocument(
|
|
60
72
|
fileName: string,
|
|
@@ -231,7 +243,7 @@ export async function loadCoreModules() {
|
|
|
231
243
|
registerCoreModules();
|
|
232
244
|
}
|
|
233
245
|
for (let i = 0; i < CoreModules.length; ++i) {
|
|
234
|
-
internModule(await parseModule(CoreModules[i]));
|
|
246
|
+
await internModule(await parseModule(CoreModules[i]));
|
|
235
247
|
}
|
|
236
248
|
}
|
|
237
249
|
|
|
@@ -248,7 +260,7 @@ async function loadModule(fileName: string, fsOptions?: any, callback?: Function
|
|
|
248
260
|
|
|
249
261
|
// Extract the AST node
|
|
250
262
|
const module = await extractAstNode<ModuleDefinition>(fileName, services);
|
|
251
|
-
const result: Module = internModule(module);
|
|
263
|
+
const result: Module = await internModule(module);
|
|
252
264
|
console.log(chalk.green(`Module ${chalk.bold(result.name)} loaded`));
|
|
253
265
|
logger.info(`Module ${result.name} loaded`);
|
|
254
266
|
if (callback) {
|
|
@@ -295,25 +307,8 @@ function getFsAdapter(fs: any) {
|
|
|
295
307
|
}
|
|
296
308
|
|
|
297
309
|
function setRbacForEntity(entity: Entity, rbacSpec: RbacSpecDefinition) {
|
|
298
|
-
const rbac: RbacSpecification[] =
|
|
299
|
-
|
|
300
|
-
const rs: RbacSpecification = new RbacSpecification().setResource(
|
|
301
|
-
makeFqName(entity.moduleName, entity.name)
|
|
302
|
-
);
|
|
303
|
-
specEntries.entries.forEach((spec: RbacSpecEntry) => {
|
|
304
|
-
if (spec.allow) {
|
|
305
|
-
rs.setPermissions(
|
|
306
|
-
spec.allow.oprs.map((v: RbacOpr) => {
|
|
307
|
-
return v.value;
|
|
308
|
-
})
|
|
309
|
-
);
|
|
310
|
-
} else if (spec.role) {
|
|
311
|
-
rs.setRoles(spec.role.roles);
|
|
312
|
-
} else if (spec.expr) {
|
|
313
|
-
rs.setExpression(spec.expr.lhs, spec.expr.rhs);
|
|
314
|
-
}
|
|
315
|
-
});
|
|
316
|
-
rbac.push(rs);
|
|
310
|
+
const rbac: RbacSpecification[] = rbacSpec.specEntries.map((rs: RbacSpecEntries) => {
|
|
311
|
+
return RbacSpecification.from(rs).setResource(makeFqName(entity.moduleName, entity.name));
|
|
317
312
|
});
|
|
318
313
|
if (rbac.length > 0) {
|
|
319
314
|
const f = async () => {
|
|
@@ -414,13 +409,126 @@ export async function runStandaloneStatements() {
|
|
|
414
409
|
}
|
|
415
410
|
}
|
|
416
411
|
|
|
417
|
-
|
|
412
|
+
async function addAgentDefinition(def: AgentDefinition, moduleName: string) {
|
|
413
|
+
let llmName: string | undefined = undefined;
|
|
414
|
+
const name = def.name;
|
|
415
|
+
let hasUserLlm = false;
|
|
416
|
+
const attrsStrs = new Array<string>();
|
|
417
|
+
attrsStrs.push(`name "${name}"`);
|
|
418
|
+
const attrs = newInstanceAttributes();
|
|
419
|
+
def.body?.attributes.forEach((apdef: AgentPropertyDef) => {
|
|
420
|
+
let v: any = undefined;
|
|
421
|
+
if (apdef.value.array) {
|
|
422
|
+
v = apdef.value.array.vals
|
|
423
|
+
.map((stmt: Statement) => {
|
|
424
|
+
if (stmt.pattern.literal) {
|
|
425
|
+
const s = stmt.pattern.literal.str;
|
|
426
|
+
if (s == undefined) {
|
|
427
|
+
throw new Error(`Only arrays of string-literals are to be passed to agent ${name}`);
|
|
428
|
+
}
|
|
429
|
+
return s;
|
|
430
|
+
} else {
|
|
431
|
+
throw new Error(`Invalid value in array passed to agent ${name}`);
|
|
432
|
+
}
|
|
433
|
+
})
|
|
434
|
+
.join(',');
|
|
435
|
+
} else {
|
|
436
|
+
v = apdef.value.str || apdef.value.id || apdef.value.num;
|
|
437
|
+
if (v == undefined) {
|
|
438
|
+
v = apdef.value.bool;
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
if (v == undefined) {
|
|
442
|
+
throw new Error(`Cannot initialize agent ${name}, only literals can be set for attributes`);
|
|
443
|
+
}
|
|
444
|
+
if (llmName == undefined && apdef.name == 'llm') {
|
|
445
|
+
llmName = v;
|
|
446
|
+
hasUserLlm = true;
|
|
447
|
+
}
|
|
448
|
+
const ov = v;
|
|
449
|
+
if (apdef.value.str || apdef.value.id || apdef.value.array) {
|
|
450
|
+
v = `"${v}"`;
|
|
451
|
+
}
|
|
452
|
+
attrsStrs.push(`${apdef.name} ${v}`);
|
|
453
|
+
attrs.set(apdef.name, ov);
|
|
454
|
+
});
|
|
455
|
+
if (!attrs.has('llm')) {
|
|
456
|
+
llmName = `${name}_llm`;
|
|
457
|
+
attrsStrs.push(`llm "${llmName}"`);
|
|
458
|
+
if (hasUserLlm) attrs.set('llm', llmName);
|
|
459
|
+
}
|
|
460
|
+
const createAgent = `{${CoreAIModuleName}/${AgentEntityName} {
|
|
461
|
+
${attrsStrs.join(',')}
|
|
462
|
+
}, @upsert}`;
|
|
463
|
+
let wf = createAgent;
|
|
464
|
+
if (llmName) {
|
|
465
|
+
wf = `{${CoreAIModuleName}/${LlmEntityName} {name "${llmName}"}, @upsert}; ${wf}`;
|
|
466
|
+
}
|
|
467
|
+
(await parseWorkflow(`workflow A {${wf}}`)).statements.forEach((stmt: Statement) => {
|
|
468
|
+
addStandaloneStatement(stmt, moduleName);
|
|
469
|
+
});
|
|
470
|
+
addAgent(def.name, attrs, moduleName);
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
function addResolverDefinition(def: ResolverDefinition, moduleName: string) {
|
|
474
|
+
const resolverName = `${moduleName}/${def.name}`;
|
|
475
|
+
const paths = def.paths;
|
|
476
|
+
if (paths.length == 0) {
|
|
477
|
+
logger.warn(`Resolver has no associated paths - ${resolverName}`);
|
|
478
|
+
return;
|
|
479
|
+
}
|
|
480
|
+
registerInitFunction(() => {
|
|
481
|
+
const methods = new Map<string, Function>();
|
|
482
|
+
let subsFn: Function | undefined;
|
|
483
|
+
let subsEvent: string | undefined;
|
|
484
|
+
def.methods.forEach((spec: ResolverMethodSpec) => {
|
|
485
|
+
const n = spec.key.name;
|
|
486
|
+
if (n == 'subscribe') {
|
|
487
|
+
subsFn = asResolverFn(spec.fn.name);
|
|
488
|
+
} else if (n == 'onSubscription') {
|
|
489
|
+
subsEvent = spec.fn.name;
|
|
490
|
+
} else {
|
|
491
|
+
methods.set(n, asResolverFn(spec.fn.name));
|
|
492
|
+
}
|
|
493
|
+
});
|
|
494
|
+
const methodsObj = Object.fromEntries(methods.entries()) as GenericResolverMethods;
|
|
495
|
+
const resolver = new GenericResolver(resolverName, methodsObj);
|
|
496
|
+
registerResolver(resolverName, () => {
|
|
497
|
+
return resolver;
|
|
498
|
+
});
|
|
499
|
+
paths.forEach((path: string) => {
|
|
500
|
+
setResolver(path, resolverName);
|
|
501
|
+
});
|
|
502
|
+
if (subsFn && subsEvent) {
|
|
503
|
+
resolver.subs = {
|
|
504
|
+
subscribe: subsFn,
|
|
505
|
+
onSubscriptionEvent: subsEvent,
|
|
506
|
+
};
|
|
507
|
+
setSubscription(subsEvent, resolverName);
|
|
508
|
+
resolver.subscribe();
|
|
509
|
+
}
|
|
510
|
+
});
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
function asResolverFn(fname: string): Function {
|
|
514
|
+
let fn = getModuleFn(fname);
|
|
515
|
+
if (fn) return fn;
|
|
516
|
+
fn = eval(fname);
|
|
517
|
+
if (!(fn instanceof Function)) {
|
|
518
|
+
throw new Error(`${fname} is not a function`);
|
|
519
|
+
}
|
|
520
|
+
return fn as Function;
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
export async function addFromDef(def: Definition, moduleName: string) {
|
|
418
524
|
if (isEntityDefinition(def)) addSchemaFromDef(def, moduleName);
|
|
419
525
|
else if (isEventDefinition(def)) addSchemaFromDef(def, moduleName);
|
|
420
526
|
else if (isRecordDefinition(def)) addSchemaFromDef(def, moduleName);
|
|
421
527
|
else if (isRelationshipDefinition(def)) addRelationshipFromDef(def, moduleName);
|
|
422
528
|
else if (isWorkflowDefinition(def)) addWorkflowFromDef(def, moduleName);
|
|
529
|
+
else if (isAgentDefinition(def)) await addAgentDefinition(def, moduleName);
|
|
423
530
|
else if (isStandaloneStatement(def)) addStandaloneStatement(def.stmt, moduleName);
|
|
531
|
+
else if (isResolverDefinition(def)) addResolverDefinition(def, moduleName);
|
|
424
532
|
}
|
|
425
533
|
|
|
426
534
|
export async function parseAndIntern(code: string, moduleName?: string) {
|
|
@@ -434,17 +542,51 @@ export async function parseAndIntern(code: string, moduleName?: string) {
|
|
|
434
542
|
if (r.parseResult.parserErrors.length > 0) {
|
|
435
543
|
throw new Error(`Parser errors: ${r.parseResult.parserErrors.join('\n')}`);
|
|
436
544
|
}
|
|
437
|
-
internModule(r.parseResult.value);
|
|
545
|
+
await internModule(r.parseResult.value);
|
|
438
546
|
}
|
|
439
547
|
|
|
440
|
-
export function internModule(module: ModuleDefinition): Module {
|
|
548
|
+
export async function internModule(module: ModuleDefinition): Promise<Module> {
|
|
441
549
|
const mn = module.name;
|
|
442
550
|
const r = addModule(mn);
|
|
443
551
|
module.imports.forEach(async (imp: Import) => {
|
|
444
552
|
await importModule(imp.path, imp.name);
|
|
445
553
|
});
|
|
446
|
-
module.defs.
|
|
447
|
-
|
|
448
|
-
|
|
554
|
+
for (let i = 0; i < module.defs.length; ++i) {
|
|
555
|
+
const def = module.defs[i];
|
|
556
|
+
await addFromDef(def, mn);
|
|
557
|
+
}
|
|
449
558
|
return r;
|
|
450
559
|
}
|
|
560
|
+
|
|
561
|
+
const JS_PREFIX = '#js';
|
|
562
|
+
|
|
563
|
+
function preprocessRawConfig(rawConfig: any): any {
|
|
564
|
+
const keys = Object.keys(rawConfig);
|
|
565
|
+
keys.forEach((k: any) => {
|
|
566
|
+
const v = rawConfig[k];
|
|
567
|
+
if (isString(v) && v.startsWith(JS_PREFIX)) {
|
|
568
|
+
const s = v.substring(3).trim();
|
|
569
|
+
rawConfig[k] = eval(s);
|
|
570
|
+
} else if (typeof v == 'object') {
|
|
571
|
+
preprocessRawConfig(v);
|
|
572
|
+
}
|
|
573
|
+
});
|
|
574
|
+
return rawConfig;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
export async function loadRawConfig(
|
|
578
|
+
configFileName: string,
|
|
579
|
+
validate: boolean = true,
|
|
580
|
+
fsOptions?: any
|
|
581
|
+
): Promise<any> {
|
|
582
|
+
const fs = await getFileSystem(fsOptions);
|
|
583
|
+
let rawConfig = preprocessRawConfig(JSON.parse(await fs.readFile(configFileName)));
|
|
584
|
+
if (validate) {
|
|
585
|
+
rawConfig = ConfigSchema.parse(rawConfig);
|
|
586
|
+
}
|
|
587
|
+
return rawConfig;
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
export function generateRawConfig(configObj: any): string {
|
|
591
|
+
return JSON.stringify(configObj);
|
|
592
|
+
}
|