agentlang 0.0.5 → 0.0.7
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/language/generated/ast.d.ts +7 -7
- package/out/language/generated/ast.d.ts.map +1 -1
- package/out/language/generated/ast.js +1 -1
- package/out/language/generated/ast.js.map +1 -1
- package/out/language/generated/grammar.js +5 -5
- package/out/language/main.cjs +6 -6
- package/out/language/main.cjs.map +2 -2
- package/out/language/parser.d.ts.map +1 -1
- package/out/language/parser.js +21 -5
- package/out/language/parser.js.map +1 -1
- package/out/language/syntax.d.ts +8 -2
- package/out/language/syntax.d.ts.map +1 -1
- package/out/language/syntax.js +42 -2
- package/out/language/syntax.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 +48 -0
- package/out/runtime/agents/common.js.map +1 -1
- package/out/runtime/agents/impl/openai.js +1 -1
- package/out/runtime/agents/impl/openai.js.map +1 -1
- package/out/runtime/auth/cognito.d.ts +2 -0
- package/out/runtime/auth/cognito.d.ts.map +1 -1
- package/out/runtime/auth/cognito.js +115 -15
- package/out/runtime/auth/cognito.js.map +1 -1
- package/out/runtime/auth/interface.d.ts +2 -0
- package/out/runtime/auth/interface.d.ts.map +1 -1
- package/out/runtime/interpreter.d.ts.map +1 -1
- package/out/runtime/interpreter.js +64 -16
- package/out/runtime/interpreter.js.map +1 -1
- package/out/runtime/jsmodules.d.ts +6 -0
- package/out/runtime/jsmodules.d.ts.map +1 -0
- package/out/runtime/jsmodules.js +138 -0
- package/out/runtime/jsmodules.js.map +1 -0
- package/out/runtime/loader.d.ts.map +1 -1
- package/out/runtime/loader.js +11 -11
- package/out/runtime/loader.js.map +1 -1
- package/out/runtime/module.d.ts +14 -1
- package/out/runtime/module.d.ts.map +1 -1
- package/out/runtime/module.js +96 -17
- package/out/runtime/module.js.map +1 -1
- package/out/runtime/modules/ai.d.ts +1 -0
- package/out/runtime/modules/ai.d.ts.map +1 -1
- package/out/runtime/modules/ai.js +20 -11
- package/out/runtime/modules/ai.js.map +1 -1
- package/out/runtime/modules/auth.d.ts +7 -3
- package/out/runtime/modules/auth.d.ts.map +1 -1
- package/out/runtime/modules/auth.js +129 -8
- package/out/runtime/modules/auth.js.map +1 -1
- package/out/runtime/resolvers/interface.d.ts +0 -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/impl.d.ts.map +1 -1
- package/out/runtime/resolvers/sqldb/impl.js +9 -3
- package/out/runtime/resolvers/sqldb/impl.js.map +1 -1
- package/out/runtime/util.d.ts +0 -4
- package/out/runtime/util.d.ts.map +1 -1
- package/out/runtime/util.js +0 -78
- package/out/runtime/util.js.map +1 -1
- package/package.json +1 -1
- package/src/language/agentlang.langium +3 -4
- package/src/language/generated/ast.ts +8 -8
- package/src/language/generated/grammar.ts +5 -5
- package/src/language/parser.ts +24 -5
- package/src/language/syntax.ts +50 -5
- package/src/runtime/agents/common.ts +48 -0
- package/src/runtime/agents/impl/openai.ts +1 -1
- package/src/runtime/auth/cognito.ts +152 -22
- package/src/runtime/auth/interface.ts +7 -0
- package/src/runtime/interpreter.ts +63 -18
- package/src/runtime/jsmodules.ts +123 -0
- package/src/runtime/loader.ts +11 -10
- package/src/runtime/module.ts +113 -18
- package/src/runtime/modules/ai.ts +22 -14
- package/src/runtime/modules/auth.ts +156 -8
- package/src/runtime/resolvers/interface.ts +0 -1
- package/src/runtime/resolvers/sqldb/impl.ts +8 -3
- package/src/runtime/util.ts +0 -70
|
@@ -6,14 +6,7 @@ import {
|
|
|
6
6
|
SignUpCallback,
|
|
7
7
|
UserInfo,
|
|
8
8
|
} from './interface.js';
|
|
9
|
-
import {
|
|
10
|
-
ensureUser,
|
|
11
|
-
ensureUserSession,
|
|
12
|
-
findUser,
|
|
13
|
-
findUserByEmail,
|
|
14
|
-
findUserSession,
|
|
15
|
-
removeSession,
|
|
16
|
-
} from '../modules/auth.js';
|
|
9
|
+
import { ensureUser, ensureUserSession, findUser, findUserByEmail } from '../modules/auth.js';
|
|
17
10
|
import { logger } from '../logger.js';
|
|
18
11
|
import { sleepMilliseconds } from '../util.js';
|
|
19
12
|
import { Instance } from '../module.js';
|
|
@@ -36,9 +29,14 @@ let fromEnv: any = undefined;
|
|
|
36
29
|
let CognitoIdentityProviderClient: any = undefined;
|
|
37
30
|
let SignUpCommand: any = undefined;
|
|
38
31
|
let AdminGetUserCommand: any = undefined;
|
|
32
|
+
let InitiateAuthCommand: any = undefined;
|
|
39
33
|
let AuthenticationDetails: any = undefined;
|
|
40
34
|
let CognitoUser: any = undefined;
|
|
41
35
|
let CognitoUserPool: any = undefined;
|
|
36
|
+
let CognitoUserSession: any = undefined;
|
|
37
|
+
let CognitoIdToken: any = undefined;
|
|
38
|
+
let CognitoAccessToken: any = undefined;
|
|
39
|
+
let CognitoRefreshToken: any = undefined;
|
|
42
40
|
|
|
43
41
|
if (isNodeEnv) {
|
|
44
42
|
const cp = await import('@aws-sdk/credential-providers');
|
|
@@ -48,11 +46,16 @@ if (isNodeEnv) {
|
|
|
48
46
|
CognitoIdentityProviderClient = cip.CognitoIdentityProviderClient;
|
|
49
47
|
SignUpCommand = cip.SignUpCommand;
|
|
50
48
|
AdminGetUserCommand = cip.AdminGetUserCommand;
|
|
49
|
+
InitiateAuthCommand = cip.InitiateAuthCommand;
|
|
51
50
|
|
|
52
51
|
const ci = await import('amazon-cognito-identity-js');
|
|
53
52
|
AuthenticationDetails = ci.AuthenticationDetails;
|
|
54
53
|
CognitoUser = ci.CognitoUser;
|
|
55
54
|
CognitoUserPool = ci.CognitoUserPool;
|
|
55
|
+
CognitoUserSession = ci.CognitoUserSession;
|
|
56
|
+
CognitoIdToken = ci.CognitoIdToken;
|
|
57
|
+
CognitoAccessToken = ci.CognitoAccessToken;
|
|
58
|
+
CognitoRefreshToken = ci.CognitoRefreshToken;
|
|
56
59
|
}
|
|
57
60
|
|
|
58
61
|
const defaultConfig = isNodeEnv
|
|
@@ -441,7 +444,13 @@ export class CognitoAuth implements AgentlangAuth {
|
|
|
441
444
|
const idToken = result.getIdToken().getJwtToken();
|
|
442
445
|
const accessToken = result.getAccessToken().getJwtToken();
|
|
443
446
|
const refreshToken = result.getRefreshToken().getToken();
|
|
444
|
-
const localSess: Instance = await ensureUserSession(
|
|
447
|
+
const localSess: Instance = await ensureUserSession(
|
|
448
|
+
userid,
|
|
449
|
+
idToken,
|
|
450
|
+
accessToken,
|
|
451
|
+
refreshToken,
|
|
452
|
+
env
|
|
453
|
+
);
|
|
445
454
|
const sessInfo: SessionInfo = {
|
|
446
455
|
sessionId: localSess.lookup('id'),
|
|
447
456
|
userId: userid,
|
|
@@ -513,7 +522,13 @@ export class CognitoAuth implements AgentlangAuth {
|
|
|
513
522
|
const idToken = result.getIdToken().getJwtToken();
|
|
514
523
|
const accessToken = result.getAccessToken().getJwtToken();
|
|
515
524
|
const refreshToken = result.getRefreshToken().getToken();
|
|
516
|
-
const localSess: Instance = await ensureUserSession(
|
|
525
|
+
const localSess: Instance = await ensureUserSession(
|
|
526
|
+
userid,
|
|
527
|
+
idToken,
|
|
528
|
+
accessToken,
|
|
529
|
+
refreshToken,
|
|
530
|
+
env
|
|
531
|
+
);
|
|
517
532
|
const sessInfo: SessionInfo = {
|
|
518
533
|
sessionId: localSess.lookup('id'),
|
|
519
534
|
userId: userid,
|
|
@@ -540,25 +555,33 @@ export class CognitoAuth implements AgentlangAuth {
|
|
|
540
555
|
return;
|
|
541
556
|
}
|
|
542
557
|
const user = new CognitoUser({
|
|
543
|
-
Username: localUser.email,
|
|
558
|
+
Username: localUser.lookup('email'),
|
|
544
559
|
Pool: this.fetchUserPool(),
|
|
545
560
|
});
|
|
561
|
+
|
|
546
562
|
let done = false;
|
|
547
563
|
let logoutError: any;
|
|
548
|
-
|
|
549
|
-
|
|
564
|
+
|
|
565
|
+
const session = new CognitoUserSession({
|
|
566
|
+
IdToken: new CognitoIdToken({ IdToken: sessionInfo.idToken }),
|
|
567
|
+
AccessToken: new CognitoAccessToken({ AccessToken: sessionInfo.accessToken }),
|
|
568
|
+
RefreshToken: new CognitoRefreshToken({ RefreshToken: sessionInfo.refreshToken }),
|
|
550
569
|
});
|
|
551
|
-
|
|
552
|
-
user.
|
|
553
|
-
|
|
570
|
+
user.setSignInUserSession(session);
|
|
571
|
+
user.globalSignOut({
|
|
572
|
+
onSuccess: function () {
|
|
573
|
+
done = true;
|
|
574
|
+
},
|
|
575
|
+
onFailure: function (err: any) {
|
|
576
|
+
done = true;
|
|
554
577
|
logger.error(`Cognito signOut error for user ${sessionInfo.userId}:`, {
|
|
555
578
|
errorName: err.name,
|
|
556
579
|
errorMessage: sanitizeErrorMessage(err.message),
|
|
557
580
|
});
|
|
558
581
|
logoutError = err;
|
|
559
|
-
}
|
|
560
|
-
done = true;
|
|
582
|
+
},
|
|
561
583
|
});
|
|
584
|
+
|
|
562
585
|
while (!done) {
|
|
563
586
|
await sleepMilliseconds(100);
|
|
564
587
|
}
|
|
@@ -568,10 +591,6 @@ export class CognitoAuth implements AgentlangAuth {
|
|
|
568
591
|
);
|
|
569
592
|
// Continue with local session cleanup even if Cognito logout fails
|
|
570
593
|
}
|
|
571
|
-
const sess = await findUserSession(localUser.id, env);
|
|
572
|
-
if (sess) {
|
|
573
|
-
await removeSession(sess.id, env);
|
|
574
|
-
}
|
|
575
594
|
logger.debug(`Successfully logged out user ${sessionInfo.userId}`);
|
|
576
595
|
if (cb) cb(true);
|
|
577
596
|
} catch (err: any) {
|
|
@@ -581,6 +600,50 @@ export class CognitoAuth implements AgentlangAuth {
|
|
|
581
600
|
}
|
|
582
601
|
}
|
|
583
602
|
|
|
603
|
+
async changePassword(
|
|
604
|
+
sessionInfo: SessionInfo,
|
|
605
|
+
newPassword: string,
|
|
606
|
+
oldPassword: string,
|
|
607
|
+
env: Environment
|
|
608
|
+
): Promise<boolean> {
|
|
609
|
+
const localUser = await findUser(sessionInfo.userId, env);
|
|
610
|
+
if (!localUser) {
|
|
611
|
+
logger.warn(`User ${sessionInfo.userId} not found for password-change`);
|
|
612
|
+
return false;
|
|
613
|
+
}
|
|
614
|
+
const email = localUser.lookup('email');
|
|
615
|
+
const user = new CognitoUser({
|
|
616
|
+
Username: email,
|
|
617
|
+
Pool: this.fetchUserPool(),
|
|
618
|
+
});
|
|
619
|
+
const session = new CognitoUserSession({
|
|
620
|
+
IdToken: new CognitoIdToken({ IdToken: sessionInfo.idToken }),
|
|
621
|
+
AccessToken: new CognitoAccessToken({ AccessToken: sessionInfo.accessToken }),
|
|
622
|
+
RefreshToken: new CognitoRefreshToken({ RefreshToken: sessionInfo.refreshToken }),
|
|
623
|
+
});
|
|
624
|
+
user.setSignInUserSession(session);
|
|
625
|
+
let done = false;
|
|
626
|
+
let cpErr: any = undefined;
|
|
627
|
+
user.changePassword(oldPassword, newPassword, (err: any, _: any) => {
|
|
628
|
+
if (err) {
|
|
629
|
+
done = true;
|
|
630
|
+
cpErr = err;
|
|
631
|
+
} else {
|
|
632
|
+
done = true;
|
|
633
|
+
}
|
|
634
|
+
});
|
|
635
|
+
|
|
636
|
+
while (!done) {
|
|
637
|
+
await sleepMilliseconds(100);
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
if (cpErr) {
|
|
641
|
+
logger.warn(`Failed to change the password for ${email} - ${cpErr.message}`);
|
|
642
|
+
return false;
|
|
643
|
+
}
|
|
644
|
+
return true;
|
|
645
|
+
}
|
|
646
|
+
|
|
584
647
|
private fetchUserPool() {
|
|
585
648
|
if (this.userPool) {
|
|
586
649
|
return this.userPool;
|
|
@@ -753,4 +816,71 @@ export class CognitoAuth implements AgentlangAuth {
|
|
|
753
816
|
};
|
|
754
817
|
}
|
|
755
818
|
}
|
|
819
|
+
|
|
820
|
+
async refreshToken(refreshTokenString: string, env: Environment): Promise<SessionInfo> {
|
|
821
|
+
try {
|
|
822
|
+
// Use InitiateAuth with REFRESH_TOKEN_AUTH flow
|
|
823
|
+
const client = new CognitoIdentityProviderClient({
|
|
824
|
+
region: process.env.AWS_REGION || 'us-west-2',
|
|
825
|
+
credentials: fromEnv(),
|
|
826
|
+
});
|
|
827
|
+
|
|
828
|
+
const command = new InitiateAuthCommand({
|
|
829
|
+
AuthFlow: 'REFRESH_TOKEN_AUTH',
|
|
830
|
+
ClientId: this.fetchClientId(),
|
|
831
|
+
AuthParameters: {
|
|
832
|
+
REFRESH_TOKEN: refreshTokenString,
|
|
833
|
+
},
|
|
834
|
+
});
|
|
835
|
+
|
|
836
|
+
const response = await client.send(command);
|
|
837
|
+
|
|
838
|
+
if (!response.AuthenticationResult) {
|
|
839
|
+
throw new UnauthorisedError('Token refresh failed');
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
const newIdToken = response.AuthenticationResult.IdToken!;
|
|
843
|
+
const newAccessToken = response.AuthenticationResult.AccessToken!;
|
|
844
|
+
const newRefreshToken = response.AuthenticationResult.RefreshToken || refreshTokenString;
|
|
845
|
+
|
|
846
|
+
// Extract user info from the new ID token
|
|
847
|
+
const idTokenPayload = JSON.parse(atob(newIdToken.split('.')[1]));
|
|
848
|
+
const userEmail = idTokenPayload.email;
|
|
849
|
+
|
|
850
|
+
// Find or create local user
|
|
851
|
+
let localUser = await findUserByEmail(userEmail, env);
|
|
852
|
+
if (!localUser) {
|
|
853
|
+
localUser = await ensureUser(userEmail, '', '', env);
|
|
854
|
+
}
|
|
855
|
+
const userId = localUser.lookup('id');
|
|
856
|
+
|
|
857
|
+
// Update local session
|
|
858
|
+
const updatedSession = await ensureUserSession(
|
|
859
|
+
userId,
|
|
860
|
+
newIdToken,
|
|
861
|
+
newAccessToken,
|
|
862
|
+
newRefreshToken,
|
|
863
|
+
env
|
|
864
|
+
);
|
|
865
|
+
|
|
866
|
+
const sessInfo: SessionInfo = {
|
|
867
|
+
sessionId: updatedSession.lookup('id'),
|
|
868
|
+
userId: userId,
|
|
869
|
+
authToken: newIdToken,
|
|
870
|
+
idToken: newIdToken,
|
|
871
|
+
accessToken: newAccessToken,
|
|
872
|
+
refreshToken: newRefreshToken,
|
|
873
|
+
systemSesionInfo: response.AuthenticationResult,
|
|
874
|
+
};
|
|
875
|
+
|
|
876
|
+
return sessInfo;
|
|
877
|
+
} catch (err: any) {
|
|
878
|
+
logger.error(`Refresh token operation failed: ${err.message}`);
|
|
879
|
+
if (err.name === 'NotAuthorizedException') {
|
|
880
|
+
throw new UnauthorisedError('Invalid or expired refresh token');
|
|
881
|
+
}
|
|
882
|
+
handleCognitoError(err, 'refreshToken');
|
|
883
|
+
throw err; // This line won't be reached due to handleCognitoError throwing
|
|
884
|
+
}
|
|
885
|
+
}
|
|
756
886
|
}
|
|
@@ -33,4 +33,11 @@ export interface AgentlangAuth {
|
|
|
33
33
|
verifyToken(token: string, env?: Environment): any;
|
|
34
34
|
getUser(userId: string, env: Environment): Promise<UserInfo>;
|
|
35
35
|
getUserByEmail(email: string, env: Environment): Promise<UserInfo>;
|
|
36
|
+
changePassword(
|
|
37
|
+
sessionInfo: SessionInfo,
|
|
38
|
+
newPassword: string,
|
|
39
|
+
oldPassword: string,
|
|
40
|
+
env: Environment
|
|
41
|
+
): Promise<boolean>;
|
|
42
|
+
refreshToken(refreshToken: string, env: Environment): Promise<SessionInfo>;
|
|
36
43
|
}
|
|
@@ -54,7 +54,6 @@ import {
|
|
|
54
54
|
escapeFqName,
|
|
55
55
|
escapeQueryName,
|
|
56
56
|
fqNameFromPath,
|
|
57
|
-
invokeModuleFn,
|
|
58
57
|
isFqName,
|
|
59
58
|
isPath,
|
|
60
59
|
isString,
|
|
@@ -78,6 +77,7 @@ import {
|
|
|
78
77
|
maybeCancelTimer,
|
|
79
78
|
setTimerRunning,
|
|
80
79
|
} from './modules/core.js';
|
|
80
|
+
import { invokeModuleFn } from './jsmodules.js';
|
|
81
81
|
|
|
82
82
|
export type Result = any;
|
|
83
83
|
|
|
@@ -590,8 +590,8 @@ export async function parseAndEvaluateStatement(
|
|
|
590
590
|
}
|
|
591
591
|
|
|
592
592
|
async function evaluatePattern(pat: Pattern, env: Environment): Promise<void> {
|
|
593
|
-
if (pat.
|
|
594
|
-
await
|
|
593
|
+
if (pat.expr) {
|
|
594
|
+
await evaluateExpression(pat.expr, env);
|
|
595
595
|
} else if (pat.crudMap) {
|
|
596
596
|
await evaluateCrudMap(pat.crudMap, env);
|
|
597
597
|
} else if (pat.forEach) {
|
|
@@ -1047,21 +1047,61 @@ async function walkJoinQueryPattern(
|
|
|
1047
1047
|
async function handleAgentInvocation(agentEventInst: Instance, env: Environment): Promise<void> {
|
|
1048
1048
|
const agent: AgentInstance = await findAgentByName(agentEventInst.name, env);
|
|
1049
1049
|
await agent.invoke(agentEventInst.lookup('message'), env);
|
|
1050
|
-
const result: string = env.getLastResult();
|
|
1051
|
-
if (
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1050
|
+
const result: string | undefined = cleanupAgentResponse(env.getLastResult());
|
|
1051
|
+
if (result) {
|
|
1052
|
+
if (agent.isPlanner()) {
|
|
1053
|
+
logger.debug(`Agent ${agent.name} generated pattern: ${result}`);
|
|
1054
|
+
try {
|
|
1055
|
+
let rs = result.trim();
|
|
1056
|
+
if (rs.startsWith('[')) {
|
|
1057
|
+
const stmts = rs.substring(1, rs.length - 1);
|
|
1058
|
+
rs = `workflow T {${stmts}}`;
|
|
1059
|
+
}
|
|
1060
|
+
if (rs.startsWith('workflow')) {
|
|
1061
|
+
const wf = await parseWorkflow(rs);
|
|
1062
|
+
if (agent.runWorkflows) {
|
|
1063
|
+
await evaluateStatements(wf.statements, env);
|
|
1064
|
+
}
|
|
1065
|
+
} else {
|
|
1066
|
+
env.setLastResult(await parseAndEvaluateStatement(rs, undefined, env));
|
|
1067
|
+
}
|
|
1068
|
+
} catch (err: any) {
|
|
1069
|
+
logger.error(
|
|
1070
|
+
`Failed to evaluate pattern generated by agent ${agent.name} - ${result}, ${err}`
|
|
1071
|
+
);
|
|
1059
1072
|
}
|
|
1060
|
-
} catch (err: any) {
|
|
1061
|
-
logger.error(
|
|
1062
|
-
`Failed to evaluate pattern generated by agent ${agent.name} - ${result}, ${err}`
|
|
1063
|
-
);
|
|
1064
1073
|
}
|
|
1074
|
+
} else {
|
|
1075
|
+
logger.warn(`Agent ${agent.name} failed to generate a response`);
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
function cleanupAgentResponse(response: string | undefined): string | undefined {
|
|
1080
|
+
if (response) {
|
|
1081
|
+
const resp = response.trim();
|
|
1082
|
+
if (resp.startsWith('[') && resp.endsWith(']')) {
|
|
1083
|
+
return resp;
|
|
1084
|
+
}
|
|
1085
|
+
const parts = resp.split('\n');
|
|
1086
|
+
const validated = parts.filter((s: string) => {
|
|
1087
|
+
const stmt = s.trim();
|
|
1088
|
+
const r =
|
|
1089
|
+
stmt.startsWith('{') ||
|
|
1090
|
+
stmt.startsWith('}') ||
|
|
1091
|
+
stmt.startsWith('if') ||
|
|
1092
|
+
stmt.startsWith('for') ||
|
|
1093
|
+
stmt.startsWith('delete') ||
|
|
1094
|
+
stmt.startsWith('workflow');
|
|
1095
|
+
if (!r) {
|
|
1096
|
+
const i = stmt.indexOf('(');
|
|
1097
|
+
return i > 0 && stmt.indexOf(')') > i;
|
|
1098
|
+
} else {
|
|
1099
|
+
return r;
|
|
1100
|
+
}
|
|
1101
|
+
});
|
|
1102
|
+
return validated.join('\n');
|
|
1103
|
+
} else {
|
|
1104
|
+
return response;
|
|
1065
1105
|
}
|
|
1066
1106
|
}
|
|
1067
1107
|
|
|
@@ -1263,7 +1303,12 @@ async function applyFn(fnCall: FnCall, env: Environment, isAsync: boolean): Prom
|
|
|
1263
1303
|
if (fnCall.args != undefined) {
|
|
1264
1304
|
args = new Array<Result>();
|
|
1265
1305
|
for (let i = 0; i < fnCall.args.length; ++i) {
|
|
1266
|
-
|
|
1306
|
+
const arg = fnCall.args[i];
|
|
1307
|
+
if (isLiteral(arg)) {
|
|
1308
|
+
await evaluateLiteral(arg, env);
|
|
1309
|
+
} else {
|
|
1310
|
+
await evaluateExpression(arg, env);
|
|
1311
|
+
}
|
|
1267
1312
|
args.push(env.getLastResult());
|
|
1268
1313
|
}
|
|
1269
1314
|
args.push(env);
|
|
@@ -1287,7 +1332,7 @@ async function realizeMap(mapLiteral: MapLiteral, env: Environment): Promise<voi
|
|
|
1287
1332
|
for (let i = 0; i < mapLiteral.entries.length; ++i) {
|
|
1288
1333
|
const entry = mapLiteral.entries[i];
|
|
1289
1334
|
const k = getMapKey(entry.key);
|
|
1290
|
-
await
|
|
1335
|
+
await evaluateExpression(entry.value, env);
|
|
1291
1336
|
result.set(k, env.getLastResult());
|
|
1292
1337
|
}
|
|
1293
1338
|
env.setLastResult(Object.fromEntries(result.entries()));
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { logger } from './logger.js';
|
|
2
|
+
import { setSubscription } from './resolvers/registry.js';
|
|
3
|
+
import { now, splitRefs } from './util.js';
|
|
4
|
+
|
|
5
|
+
const importedModules = new Map<string, any>();
|
|
6
|
+
|
|
7
|
+
// Usage: importModule("./mymodels/acme.js")
|
|
8
|
+
export async function importModule(path: string, name: string) {
|
|
9
|
+
if (!(path.startsWith('/') || path.startsWith('.'))) {
|
|
10
|
+
path = process.cwd() + '/' + path;
|
|
11
|
+
}
|
|
12
|
+
const m = await import(/* @vite-ignore */ path);
|
|
13
|
+
importedModules.set(name, m);
|
|
14
|
+
// e.g of dynamic fn-call:
|
|
15
|
+
//// let f = eval("(a, b) => m.add(a, b)");
|
|
16
|
+
//// console.log(f(10, 20))
|
|
17
|
+
return m;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function moduleImported(moduleName: string): boolean {
|
|
21
|
+
return importedModules.has(moduleName);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const ReservedImports = new Set<string>(['resolvers']);
|
|
25
|
+
|
|
26
|
+
export function valiadteImportName(n: string) {
|
|
27
|
+
if (ReservedImports.has(n)) {
|
|
28
|
+
throw new Error(`${n} is an import reserved by the runtime`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function maybeEvalFunction(fnName: string): Function | undefined {
|
|
33
|
+
try {
|
|
34
|
+
return eval(fnName);
|
|
35
|
+
} catch (reason: any) {
|
|
36
|
+
logger.debug(reason);
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function invokeReservedFn(moduleName: string, fnName: string, args: Array<any> | null) {
|
|
42
|
+
if (moduleName == 'resolvers' && fnName == 'setSubscription' && args != null) {
|
|
43
|
+
return setSubscription(args[0], args[1]);
|
|
44
|
+
} else {
|
|
45
|
+
throw new Error(`Failed to call ${moduleName}.${fnName} with the given arguments`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async function invokeBuiltInFn(fnName: string, args: Array<any> | null, isAsync: boolean = false) {
|
|
50
|
+
if (fnName == 'now') {
|
|
51
|
+
return now();
|
|
52
|
+
} else if (fnName == 'uuid') {
|
|
53
|
+
return crypto.randomUUID();
|
|
54
|
+
} else {
|
|
55
|
+
const pf: Function | undefined = maybeEvalFunction(fnName);
|
|
56
|
+
if (pf instanceof Function) {
|
|
57
|
+
if (args == null) {
|
|
58
|
+
if (isAsync) return await pf();
|
|
59
|
+
else return pf();
|
|
60
|
+
} else {
|
|
61
|
+
if (isAsync) return await pf(...args.slice(0, args.length - 1));
|
|
62
|
+
else return pf(...args.slice(0, args.length - 1));
|
|
63
|
+
}
|
|
64
|
+
} else {
|
|
65
|
+
throw new Error(`Failed to invoke function - ${fnName}`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export async function invokeModuleFn(
|
|
71
|
+
fqFnName: string,
|
|
72
|
+
args: Array<any> | null,
|
|
73
|
+
isAsync: boolean = false
|
|
74
|
+
): Promise<any> {
|
|
75
|
+
try {
|
|
76
|
+
const refs: string[] = splitRefs(fqFnName);
|
|
77
|
+
if (refs.length == 1) {
|
|
78
|
+
if (isAsync) {
|
|
79
|
+
return await invokeBuiltInFn(refs[0], args, isAsync);
|
|
80
|
+
} else {
|
|
81
|
+
return invokeBuiltInFn(refs[0], args);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
const mname = refs[0];
|
|
85
|
+
if (ReservedImports.has(mname)) {
|
|
86
|
+
return invokeReservedFn(mname, refs[1], args);
|
|
87
|
+
}
|
|
88
|
+
const m = importedModules.get(mname);
|
|
89
|
+
if (m != undefined) {
|
|
90
|
+
const f = m[refs[1]];
|
|
91
|
+
if (f != undefined) {
|
|
92
|
+
if (args == null)
|
|
93
|
+
if (isAsync) {
|
|
94
|
+
return await f();
|
|
95
|
+
} else return f();
|
|
96
|
+
else if (isAsync) {
|
|
97
|
+
return await f(...args);
|
|
98
|
+
} else return f(...args);
|
|
99
|
+
} else throw new Error(`Function not found - ${fqFnName}`);
|
|
100
|
+
} else throw new Error(`JavaScript module ${refs[0]} not found`);
|
|
101
|
+
} catch (reason: any) {
|
|
102
|
+
const pf: Function | undefined = maybeEvalFunction(fqFnName);
|
|
103
|
+
if (pf instanceof Function) {
|
|
104
|
+
if (args == null) {
|
|
105
|
+
if (isAsync) return await pf();
|
|
106
|
+
else return pf();
|
|
107
|
+
} else {
|
|
108
|
+
if (isAsync) return await pf(...args.slice(0, args.length - 1));
|
|
109
|
+
else return pf(...args.slice(0, args.length - 1));
|
|
110
|
+
}
|
|
111
|
+
} else {
|
|
112
|
+
throw new Error(reason);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export function getModuleFn(fqFnName: string): Function | undefined {
|
|
118
|
+
const refs: string[] = splitRefs(fqFnName);
|
|
119
|
+
const m = importedModules.get(refs[0]);
|
|
120
|
+
if (m != undefined) {
|
|
121
|
+
return m[refs[1]];
|
|
122
|
+
} else return undefined;
|
|
123
|
+
}
|
package/src/runtime/loader.ts
CHANGED
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
ResolverDefinition,
|
|
24
24
|
ResolverMethodSpec,
|
|
25
25
|
AgentPropertyDef,
|
|
26
|
+
isLiteral,
|
|
26
27
|
} from '../language/generated/ast.js';
|
|
27
28
|
import {
|
|
28
29
|
addEntity,
|
|
@@ -45,14 +46,11 @@ import {
|
|
|
45
46
|
} from './module.js';
|
|
46
47
|
import {
|
|
47
48
|
findRbacSchema,
|
|
48
|
-
getModuleFn,
|
|
49
|
-
importModule,
|
|
50
49
|
isString,
|
|
51
50
|
makeFqName,
|
|
52
51
|
maybeExtends,
|
|
53
52
|
registerInitFunction,
|
|
54
53
|
runShellCommand,
|
|
55
|
-
//runShellCommand,
|
|
56
54
|
} from './util.js';
|
|
57
55
|
import { getFileSystem, toFsPath, readFile, readdir, exists } from '../utils/fs-utils.js';
|
|
58
56
|
import { URI } from 'vscode-uri';
|
|
@@ -67,6 +65,7 @@ import { AgentEntityName, CoreAIModuleName, LlmEntityName } from './modules/ai.j
|
|
|
67
65
|
import { GenericResolver, GenericResolverMethods } from './resolvers/interface.js';
|
|
68
66
|
import { registerResolver, setResolver, setSubscription } from './resolvers/registry.js';
|
|
69
67
|
import { ConfigSchema } from './state.js';
|
|
68
|
+
import { getModuleFn, importModule, valiadteImportName } from './jsmodules.js';
|
|
70
69
|
|
|
71
70
|
export async function extractDocument(
|
|
72
71
|
fileName: string,
|
|
@@ -403,7 +402,7 @@ export async function runStandaloneStatements() {
|
|
|
403
402
|
GlobalEnvironment.switchActiveModuleName(oldModule);
|
|
404
403
|
}
|
|
405
404
|
}
|
|
406
|
-
logger.
|
|
405
|
+
logger.debug(`Init eval result: ${GlobalEnvironment.getLastResult()}`);
|
|
407
406
|
});
|
|
408
407
|
StandaloneStatements.clear();
|
|
409
408
|
}
|
|
@@ -421,10 +420,12 @@ async function addAgentDefinition(def: AgentDefinition, moduleName: string) {
|
|
|
421
420
|
if (apdef.value.array) {
|
|
422
421
|
v = apdef.value.array.vals
|
|
423
422
|
.map((stmt: Statement) => {
|
|
424
|
-
if (stmt.pattern.
|
|
425
|
-
const s = stmt.pattern.
|
|
423
|
+
if (stmt.pattern.expr && isLiteral(stmt.pattern.expr)) {
|
|
424
|
+
const s = stmt.pattern.expr.str || stmt.pattern.expr.id;
|
|
426
425
|
if (s == undefined) {
|
|
427
|
-
throw new Error(
|
|
426
|
+
throw new Error(
|
|
427
|
+
`Only arrays of string-literals or identifiers should be passed to agent ${name}`
|
|
428
|
+
);
|
|
428
429
|
}
|
|
429
430
|
return s;
|
|
430
431
|
} else {
|
|
@@ -499,12 +500,11 @@ function addResolverDefinition(def: ResolverDefinition, moduleName: string) {
|
|
|
499
500
|
paths.forEach((path: string) => {
|
|
500
501
|
setResolver(path, resolverName);
|
|
501
502
|
});
|
|
502
|
-
if (subsFn
|
|
503
|
+
if (subsFn) {
|
|
503
504
|
resolver.subs = {
|
|
504
505
|
subscribe: subsFn,
|
|
505
|
-
onSubscriptionEvent: subsEvent,
|
|
506
506
|
};
|
|
507
|
-
setSubscription(subsEvent, resolverName);
|
|
507
|
+
if (subsEvent) setSubscription(subsEvent, resolverName);
|
|
508
508
|
resolver.subscribe();
|
|
509
509
|
}
|
|
510
510
|
});
|
|
@@ -549,6 +549,7 @@ export async function internModule(module: ModuleDefinition): Promise<Module> {
|
|
|
549
549
|
const mn = module.name;
|
|
550
550
|
const r = addModule(mn);
|
|
551
551
|
module.imports.forEach(async (imp: Import) => {
|
|
552
|
+
valiadteImportName(imp.name);
|
|
552
553
|
await importModule(imp.path, imp.name);
|
|
553
554
|
});
|
|
554
555
|
for (let i = 0; i < module.defs.length; ++i) {
|