agentlang 0.0.3 → 0.0.4
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 +12 -0
- 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 +80 -18
- package/out/language/generated/ast.d.ts.map +1 -1
- package/out/language/generated/ast.js +119 -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 +831 -238
- 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 +995 -331
- 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 +148 -29
- package/out/runtime/loader.js.map +1 -1
- package/out/runtime/module.d.ts +48 -5
- package/out/runtime/module.d.ts.map +1 -1
- package/out/runtime/module.js +200 -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 +282 -30
- 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/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 +4 -0
- package/out/runtime/util.d.ts.map +1 -1
- package/out/runtime/util.js +16 -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 +15 -0
- package/src/cli/main.ts +6 -12
- package/src/language/agentlang.langium +31 -10
- package/src/language/generated/ast.ts +212 -44
- package/src/language/generated/grammar.ts +831 -238
- 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 +159 -30
- package/src/runtime/module.ts +243 -10
- package/src/runtime/modules/ai.ts +52 -28
- package/src/runtime/modules/auth.ts +330 -38
- 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/state.ts +11 -1
- package/src/runtime/util.ts +17 -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,13 @@ import {
|
|
|
19
17
|
Statement,
|
|
20
18
|
isStandaloneStatement,
|
|
21
19
|
SchemaDefinition,
|
|
20
|
+
isAgentDefinition,
|
|
21
|
+
AgentDefinition,
|
|
22
|
+
SetAttribute,
|
|
23
|
+
isLiteral,
|
|
24
|
+
isResolverDefinition,
|
|
25
|
+
ResolverDefinition,
|
|
26
|
+
ResolverMethodSpec,
|
|
22
27
|
} from '../language/generated/ast.js';
|
|
23
28
|
import {
|
|
24
29
|
addEntity,
|
|
@@ -36,10 +41,14 @@ import {
|
|
|
36
41
|
isModule,
|
|
37
42
|
getUserModuleNames,
|
|
38
43
|
removeModule,
|
|
44
|
+
newInstanceAttributes,
|
|
45
|
+
addAgent,
|
|
39
46
|
} from './module.js';
|
|
40
47
|
import {
|
|
41
48
|
findRbacSchema,
|
|
49
|
+
getModuleFn,
|
|
42
50
|
importModule,
|
|
51
|
+
isString,
|
|
43
52
|
makeFqName,
|
|
44
53
|
maybeExtends,
|
|
45
54
|
registerInitFunction,
|
|
@@ -51,10 +60,14 @@ import { URI } from 'vscode-uri';
|
|
|
51
60
|
import { AstNode, LangiumCoreServices, LangiumDocument } from 'langium';
|
|
52
61
|
import { isNodeEnv, path } from '../utils/runtime.js';
|
|
53
62
|
import { CoreModules, registerCoreModules } from './modules/core.js';
|
|
54
|
-
import { parse, parseModule } from '../language/parser.js';
|
|
63
|
+
import { parse, parseModule, parseWorkflow } from '../language/parser.js';
|
|
55
64
|
import { logger } from './logger.js';
|
|
56
65
|
import { Environment, evaluateStatements, GlobalEnvironment } from './interpreter.js';
|
|
57
66
|
import { createPermission, createRole } from './modules/auth.js';
|
|
67
|
+
import { AgentEntityName, CoreAIModuleName, LlmEntityName } from './modules/ai.js';
|
|
68
|
+
import { GenericResolver, GenericResolverMethods } from './resolvers/interface.js';
|
|
69
|
+
import { registerResolver, setResolver, setSubscription } from './resolvers/registry.js';
|
|
70
|
+
import { ConfigSchema } from './state.js';
|
|
58
71
|
|
|
59
72
|
export async function extractDocument(
|
|
60
73
|
fileName: string,
|
|
@@ -231,7 +244,7 @@ export async function loadCoreModules() {
|
|
|
231
244
|
registerCoreModules();
|
|
232
245
|
}
|
|
233
246
|
for (let i = 0; i < CoreModules.length; ++i) {
|
|
234
|
-
internModule(await parseModule(CoreModules[i]));
|
|
247
|
+
await internModule(await parseModule(CoreModules[i]));
|
|
235
248
|
}
|
|
236
249
|
}
|
|
237
250
|
|
|
@@ -248,7 +261,7 @@ async function loadModule(fileName: string, fsOptions?: any, callback?: Function
|
|
|
248
261
|
|
|
249
262
|
// Extract the AST node
|
|
250
263
|
const module = await extractAstNode<ModuleDefinition>(fileName, services);
|
|
251
|
-
const result: Module = internModule(module);
|
|
264
|
+
const result: Module = await internModule(module);
|
|
252
265
|
console.log(chalk.green(`Module ${chalk.bold(result.name)} loaded`));
|
|
253
266
|
logger.info(`Module ${result.name} loaded`);
|
|
254
267
|
if (callback) {
|
|
@@ -295,25 +308,8 @@ function getFsAdapter(fs: any) {
|
|
|
295
308
|
}
|
|
296
309
|
|
|
297
310
|
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);
|
|
311
|
+
const rbac: RbacSpecification[] = rbacSpec.specEntries.map((rs: RbacSpecEntries) => {
|
|
312
|
+
return RbacSpecification.from(rs).setResource(makeFqName(entity.moduleName, entity.name));
|
|
317
313
|
});
|
|
318
314
|
if (rbac.length > 0) {
|
|
319
315
|
const f = async () => {
|
|
@@ -414,13 +410,112 @@ export async function runStandaloneStatements() {
|
|
|
414
410
|
}
|
|
415
411
|
}
|
|
416
412
|
|
|
417
|
-
|
|
413
|
+
async function addAgentDefinition(def: AgentDefinition, moduleName: string) {
|
|
414
|
+
let llmName: string | undefined = undefined;
|
|
415
|
+
const name = def.name;
|
|
416
|
+
let hasUserLlm = false;
|
|
417
|
+
const attrsStrs = new Array<string>();
|
|
418
|
+
attrsStrs.push(`name "${name}"`);
|
|
419
|
+
const attrs = newInstanceAttributes();
|
|
420
|
+
def.body?.attributes.forEach((sa: SetAttribute) => {
|
|
421
|
+
let v: any = undefined;
|
|
422
|
+
if (isLiteral(sa.value)) {
|
|
423
|
+
v = sa.value.str || sa.value.id || sa.value.num;
|
|
424
|
+
if (v == undefined) {
|
|
425
|
+
v = sa.value.bool;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
if (v == undefined) {
|
|
429
|
+
throw new Error(`Cannot initialize agent ${name}, only literals can be set for attributes`);
|
|
430
|
+
}
|
|
431
|
+
if (llmName == undefined && sa.name == 'llm') {
|
|
432
|
+
llmName = v;
|
|
433
|
+
hasUserLlm = true;
|
|
434
|
+
}
|
|
435
|
+
const ov = v;
|
|
436
|
+
if (isLiteral(sa.value) && (sa.value.str || sa.value.id)) {
|
|
437
|
+
v = `"${v}"`;
|
|
438
|
+
}
|
|
439
|
+
attrsStrs.push(`${sa.name} ${v}`);
|
|
440
|
+
attrs.set(sa.name, ov);
|
|
441
|
+
});
|
|
442
|
+
if (!attrs.has('llm')) {
|
|
443
|
+
llmName = `${name}_llm`;
|
|
444
|
+
attrsStrs.push(`llm "${llmName}"`);
|
|
445
|
+
if (hasUserLlm) attrs.set('llm', llmName);
|
|
446
|
+
}
|
|
447
|
+
const createAgent = `{${CoreAIModuleName}/${AgentEntityName} {
|
|
448
|
+
${attrsStrs.join(',')}
|
|
449
|
+
}, @upsert}`;
|
|
450
|
+
let wf = createAgent;
|
|
451
|
+
if (llmName) {
|
|
452
|
+
wf = `{${CoreAIModuleName}/${LlmEntityName} {name "${llmName}"}, @upsert}; ${wf}`;
|
|
453
|
+
}
|
|
454
|
+
(await parseWorkflow(`workflow A {${wf}}`)).statements.forEach((stmt: Statement) => {
|
|
455
|
+
addStandaloneStatement(stmt, moduleName);
|
|
456
|
+
});
|
|
457
|
+
addAgent(def.name, attrs, moduleName);
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
function addResolverDefinition(def: ResolverDefinition, moduleName: string) {
|
|
461
|
+
const resolverName = `${moduleName}/${def.name}`;
|
|
462
|
+
const paths = def.paths;
|
|
463
|
+
if (paths.length == 0) {
|
|
464
|
+
logger.warn(`Resolver has no associated paths - ${resolverName}`);
|
|
465
|
+
return;
|
|
466
|
+
}
|
|
467
|
+
registerInitFunction(() => {
|
|
468
|
+
const methods = new Map<string, Function>();
|
|
469
|
+
let subsFn: Function | undefined;
|
|
470
|
+
let subsEvent: string | undefined;
|
|
471
|
+
def.methods.forEach((spec: ResolverMethodSpec) => {
|
|
472
|
+
const n = spec.key.name;
|
|
473
|
+
if (n == 'subscribe') {
|
|
474
|
+
subsFn = asResolverFn(spec.fn.name);
|
|
475
|
+
} else if (n == 'onSubscription') {
|
|
476
|
+
subsEvent = spec.fn.name;
|
|
477
|
+
} else {
|
|
478
|
+
methods.set(n, asResolverFn(spec.fn.name));
|
|
479
|
+
}
|
|
480
|
+
});
|
|
481
|
+
const methodsObj = Object.fromEntries(methods.entries()) as GenericResolverMethods;
|
|
482
|
+
const resolver = new GenericResolver(resolverName, methodsObj);
|
|
483
|
+
registerResolver(resolverName, () => {
|
|
484
|
+
return resolver;
|
|
485
|
+
});
|
|
486
|
+
paths.forEach((path: string) => {
|
|
487
|
+
setResolver(path, resolverName);
|
|
488
|
+
});
|
|
489
|
+
if (subsFn && subsEvent) {
|
|
490
|
+
resolver.subs = {
|
|
491
|
+
subscribe: subsFn,
|
|
492
|
+
onSubscriptionEvent: subsEvent,
|
|
493
|
+
};
|
|
494
|
+
setSubscription(subsEvent, resolverName);
|
|
495
|
+
resolver.subscribe();
|
|
496
|
+
}
|
|
497
|
+
});
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
function asResolverFn(fname: string): Function {
|
|
501
|
+
let fn = getModuleFn(fname);
|
|
502
|
+
if (fn) return fn;
|
|
503
|
+
fn = eval(fname);
|
|
504
|
+
if (!(fn instanceof Function)) {
|
|
505
|
+
throw new Error(`${fname} is not a function`);
|
|
506
|
+
}
|
|
507
|
+
return fn as Function;
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
export async function addFromDef(def: Definition, moduleName: string) {
|
|
418
511
|
if (isEntityDefinition(def)) addSchemaFromDef(def, moduleName);
|
|
419
512
|
else if (isEventDefinition(def)) addSchemaFromDef(def, moduleName);
|
|
420
513
|
else if (isRecordDefinition(def)) addSchemaFromDef(def, moduleName);
|
|
421
514
|
else if (isRelationshipDefinition(def)) addRelationshipFromDef(def, moduleName);
|
|
422
515
|
else if (isWorkflowDefinition(def)) addWorkflowFromDef(def, moduleName);
|
|
516
|
+
else if (isAgentDefinition(def)) await addAgentDefinition(def, moduleName);
|
|
423
517
|
else if (isStandaloneStatement(def)) addStandaloneStatement(def.stmt, moduleName);
|
|
518
|
+
else if (isResolverDefinition(def)) addResolverDefinition(def, moduleName);
|
|
424
519
|
}
|
|
425
520
|
|
|
426
521
|
export async function parseAndIntern(code: string, moduleName?: string) {
|
|
@@ -434,17 +529,51 @@ export async function parseAndIntern(code: string, moduleName?: string) {
|
|
|
434
529
|
if (r.parseResult.parserErrors.length > 0) {
|
|
435
530
|
throw new Error(`Parser errors: ${r.parseResult.parserErrors.join('\n')}`);
|
|
436
531
|
}
|
|
437
|
-
internModule(r.parseResult.value);
|
|
532
|
+
await internModule(r.parseResult.value);
|
|
438
533
|
}
|
|
439
534
|
|
|
440
|
-
export function internModule(module: ModuleDefinition): Module {
|
|
535
|
+
export async function internModule(module: ModuleDefinition): Promise<Module> {
|
|
441
536
|
const mn = module.name;
|
|
442
537
|
const r = addModule(mn);
|
|
443
538
|
module.imports.forEach(async (imp: Import) => {
|
|
444
539
|
await importModule(imp.path, imp.name);
|
|
445
540
|
});
|
|
446
|
-
module.defs.
|
|
447
|
-
|
|
448
|
-
|
|
541
|
+
for (let i = 0; i < module.defs.length; ++i) {
|
|
542
|
+
const def = module.defs[i];
|
|
543
|
+
await addFromDef(def, mn);
|
|
544
|
+
}
|
|
449
545
|
return r;
|
|
450
546
|
}
|
|
547
|
+
|
|
548
|
+
const JS_PREFIX = '#js';
|
|
549
|
+
|
|
550
|
+
function preprocessRawConfig(rawConfig: any): any {
|
|
551
|
+
const keys = Object.keys(rawConfig);
|
|
552
|
+
keys.forEach((k: any) => {
|
|
553
|
+
const v = rawConfig[k];
|
|
554
|
+
if (isString(v) && v.startsWith(JS_PREFIX)) {
|
|
555
|
+
const s = v.substring(3).trim();
|
|
556
|
+
rawConfig[k] = eval(s);
|
|
557
|
+
} else if (typeof v == 'object') {
|
|
558
|
+
preprocessRawConfig(v);
|
|
559
|
+
}
|
|
560
|
+
});
|
|
561
|
+
return rawConfig;
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
export async function loadRawConfig(
|
|
565
|
+
configFileName: string,
|
|
566
|
+
validate: boolean = true,
|
|
567
|
+
fsOptions?: any
|
|
568
|
+
): Promise<any> {
|
|
569
|
+
const fs = await getFileSystem(fsOptions);
|
|
570
|
+
let rawConfig = preprocessRawConfig(JSON.parse(await fs.readFile(configFileName)));
|
|
571
|
+
if (validate) {
|
|
572
|
+
rawConfig = ConfigSchema.parse(rawConfig);
|
|
573
|
+
}
|
|
574
|
+
return rawConfig;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
export function generateRawConfig(configObj: any): string {
|
|
578
|
+
return JSON.stringify(configObj);
|
|
579
|
+
}
|