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
package/src/runtime/module.ts
CHANGED
|
@@ -44,6 +44,7 @@ import {
|
|
|
44
44
|
import { parseStatement } from '../language/parser.js';
|
|
45
45
|
import { ActiveSessionInfo, AdminSession } from './auth/defs.js';
|
|
46
46
|
import { DefaultIdAttributeName, PathAttributeName } from './defs.js';
|
|
47
|
+
import { logger } from './logger.js';
|
|
47
48
|
|
|
48
49
|
export class ModuleEntry {
|
|
49
50
|
name: string;
|
|
@@ -101,7 +102,7 @@ function recordSchemaToString(scm: RecordSchema): string {
|
|
|
101
102
|
ss.push(` ${n} ${attributeSpecToString(attrSpec)}`);
|
|
102
103
|
}
|
|
103
104
|
});
|
|
104
|
-
return `\n${ss.join(',\n')}
|
|
105
|
+
return `\n${ss.join(',\n')}`;
|
|
105
106
|
}
|
|
106
107
|
|
|
107
108
|
function attributeSpecToString(attrSpec: AttributeSpec): string {
|
|
@@ -142,7 +143,7 @@ function normalizeMetaValue(metaValue: any): any {
|
|
|
142
143
|
const v: Literal = metaValue as Literal;
|
|
143
144
|
if (v.array) {
|
|
144
145
|
return v.array.vals.map((value: Statement) => {
|
|
145
|
-
return normalizeMetaValue(value.pattern.
|
|
146
|
+
return normalizeMetaValue(value.pattern.expr);
|
|
146
147
|
});
|
|
147
148
|
} else if (v.bool != undefined) {
|
|
148
149
|
return v.bool;
|
|
@@ -177,6 +178,23 @@ function asTriggerInfo(te: TriggerEntry): TriggerInfo {
|
|
|
177
178
|
};
|
|
178
179
|
}
|
|
179
180
|
|
|
181
|
+
const EnumPropertyName = 'one-of';
|
|
182
|
+
const OneOfPropertyName = 'one-of-ref';
|
|
183
|
+
|
|
184
|
+
export function enumAttributeSpec(values: Set<string>): AttributeSpec {
|
|
185
|
+
return {
|
|
186
|
+
type: 'String',
|
|
187
|
+
properties: new Map().set(EnumPropertyName, values),
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export function oneOfAttributeSpec(ref: string): AttributeSpec {
|
|
192
|
+
return {
|
|
193
|
+
type: 'String',
|
|
194
|
+
properties: new Map().set(OneOfPropertyName, ref),
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
|
|
180
198
|
export class Record extends ModuleEntry {
|
|
181
199
|
schema: RecordSchema;
|
|
182
200
|
meta: Meta | undefined;
|
|
@@ -241,9 +259,9 @@ export class Record extends ModuleEntry {
|
|
|
241
259
|
}
|
|
242
260
|
if (isArrayType) props.set('array', true);
|
|
243
261
|
if (isObjectType) props.set('object', true);
|
|
244
|
-
if (enumValues) props.set(
|
|
262
|
+
if (enumValues) props.set(EnumPropertyName, new Set(enumValues));
|
|
245
263
|
if (oneOfRef) {
|
|
246
|
-
props.set(
|
|
264
|
+
props.set(OneOfPropertyName, oneOfRef);
|
|
247
265
|
this.addOneOfRefAttribute(a.name);
|
|
248
266
|
}
|
|
249
267
|
}
|
|
@@ -424,9 +442,9 @@ export class Record extends ModuleEntry {
|
|
|
424
442
|
const rbs = this.rbac.map((rs: RbacSpecification) => {
|
|
425
443
|
return rs.toString();
|
|
426
444
|
});
|
|
427
|
-
scms = `${scms} @rbac [${rbs.join(',\n')}]`;
|
|
445
|
+
scms = `${scms},\n @rbac [${rbs.join(',\n')}]`;
|
|
428
446
|
}
|
|
429
|
-
return s.concat('\n{', scms, '}\n');
|
|
447
|
+
return s.concat('\n{', scms, '\n}\n');
|
|
430
448
|
}
|
|
431
449
|
|
|
432
450
|
getUserAttributes(): RecordSchema {
|
|
@@ -532,7 +550,7 @@ function normalizeKvPairValue(kvp: KvPair): any | null {
|
|
|
532
550
|
} else if (v.num != undefined) {
|
|
533
551
|
return v.num;
|
|
534
552
|
} else if (v.bool != undefined) {
|
|
535
|
-
return v.bool;
|
|
553
|
+
return v.bool == 'true' ? true : false;
|
|
536
554
|
} else if (v.id != undefined) {
|
|
537
555
|
return v.id;
|
|
538
556
|
} else if (v.ref != undefined) {
|
|
@@ -602,14 +620,16 @@ export class RbacSpecification {
|
|
|
602
620
|
}
|
|
603
621
|
|
|
604
622
|
setPermissions(perms: Array<string>): RbacSpecification {
|
|
623
|
+
const ps = new Set<RbacPermissionFlag>();
|
|
605
624
|
perms.forEach((v: string) => {
|
|
606
625
|
const idx: any = v.toUpperCase();
|
|
607
626
|
const a: any = RbacPermissionFlag[idx];
|
|
608
627
|
if (a == undefined) {
|
|
609
628
|
throw new Error(`Not a valid RBAC permission - ${v}`);
|
|
610
629
|
}
|
|
611
|
-
|
|
630
|
+
ps.add(a);
|
|
612
631
|
});
|
|
632
|
+
this.permissions = ps;
|
|
613
633
|
return this;
|
|
614
634
|
}
|
|
615
635
|
|
|
@@ -644,9 +664,15 @@ export class RbacSpecification {
|
|
|
644
664
|
return this;
|
|
645
665
|
}
|
|
646
666
|
|
|
667
|
+
removeRoles(): RbacSpecification {
|
|
668
|
+
this.roles = RbacSpecification.EmptyRoles;
|
|
669
|
+
return this;
|
|
670
|
+
}
|
|
671
|
+
|
|
647
672
|
setExpression(lhs: string, rhs: string): RbacSpecification {
|
|
648
673
|
if (this.roles != RbacSpecification.EmptyRoles) {
|
|
649
|
-
|
|
674
|
+
logger.warn('Cannot set `where` expression along with roles, removing roles');
|
|
675
|
+
this.removeRoles();
|
|
650
676
|
}
|
|
651
677
|
this.expression = {
|
|
652
678
|
lhs: lhs,
|
|
@@ -655,7 +681,15 @@ export class RbacSpecification {
|
|
|
655
681
|
return this;
|
|
656
682
|
}
|
|
657
683
|
|
|
684
|
+
removeExpression(): RbacSpecification {
|
|
685
|
+
this.expression = undefined;
|
|
686
|
+
return this;
|
|
687
|
+
}
|
|
688
|
+
|
|
658
689
|
toString(): string {
|
|
690
|
+
if (this.permissions.size <= 0) {
|
|
691
|
+
throw new Error(`Cannot emit RbacSpecification, no permissions are set`);
|
|
692
|
+
}
|
|
659
693
|
const rs = new Array<string>();
|
|
660
694
|
this.roles.forEach((r: string) => {
|
|
661
695
|
rs.push(r);
|
|
@@ -875,6 +909,10 @@ function asRelNodeEntry(n: NodeDefinition): RelationshipNode {
|
|
|
875
909
|
};
|
|
876
910
|
}
|
|
877
911
|
|
|
912
|
+
const OneToOne = 'one_one';
|
|
913
|
+
const OneToMany = 'one_many';
|
|
914
|
+
const ManyToMany = 'many_many';
|
|
915
|
+
|
|
878
916
|
export class Relationship extends Record {
|
|
879
917
|
override type: RecordType = RecordType.RELATIONSHIP;
|
|
880
918
|
relType: RelType = RelType.CONTAINS;
|
|
@@ -953,25 +991,52 @@ export class Relationship extends Record {
|
|
|
953
991
|
return false;
|
|
954
992
|
}
|
|
955
993
|
|
|
994
|
+
private setProperty(p: string, v: any): Relationship {
|
|
995
|
+
if (this.properties == undefined) {
|
|
996
|
+
this.properties = new Map();
|
|
997
|
+
}
|
|
998
|
+
this.properties.set(p, v);
|
|
999
|
+
return this;
|
|
1000
|
+
}
|
|
1001
|
+
|
|
956
1002
|
isOneToOne(): boolean {
|
|
957
|
-
return this.isBetween() && this.hasBooleanFlagSet(
|
|
1003
|
+
return this.isBetween() && this.hasBooleanFlagSet(OneToOne);
|
|
958
1004
|
}
|
|
959
1005
|
|
|
960
1006
|
isOneToMany(): boolean {
|
|
961
|
-
return this.isBetween() && this.hasBooleanFlagSet(
|
|
1007
|
+
return this.isBetween() && this.hasBooleanFlagSet(OneToMany);
|
|
962
1008
|
}
|
|
963
1009
|
|
|
964
1010
|
isManyToMany(): boolean {
|
|
965
1011
|
if (this.isBetween()) {
|
|
966
1012
|
return (
|
|
967
|
-
this.hasBooleanFlagSet(
|
|
968
|
-
(!this.hasBooleanFlagSet(
|
|
1013
|
+
this.hasBooleanFlagSet(ManyToMany) ||
|
|
1014
|
+
(!this.hasBooleanFlagSet(OneToOne) && !this.hasBooleanFlagSet(OneToMany))
|
|
969
1015
|
);
|
|
970
1016
|
} else {
|
|
971
1017
|
return false;
|
|
972
1018
|
}
|
|
973
1019
|
}
|
|
974
1020
|
|
|
1021
|
+
setOneToOne(flag: boolean = true): Relationship {
|
|
1022
|
+
if (flag) {
|
|
1023
|
+
this.setOneToMany(false).setManyToMany(false);
|
|
1024
|
+
}
|
|
1025
|
+
return this.setProperty(OneToOne, flag);
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
setOneToMany(flag: boolean = true): Relationship {
|
|
1029
|
+
if (flag) {
|
|
1030
|
+
this.setOneToOne(false).setManyToMany(false);
|
|
1031
|
+
}
|
|
1032
|
+
return this.setProperty(OneToMany, flag);
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
setManyToMany(flag: boolean = true): Relationship {
|
|
1036
|
+
this.setOneToOne(false).setOneToMany(false);
|
|
1037
|
+
return this.setProperty(ManyToMany, flag);
|
|
1038
|
+
}
|
|
1039
|
+
|
|
975
1040
|
isFirstNode(inst: Instance): boolean {
|
|
976
1041
|
return this.isFirstNodeName(inst.getFqName());
|
|
977
1042
|
}
|
|
@@ -1561,22 +1626,46 @@ function getAnyProperty(propName: string, attrSpec: AttributeSpec): any | undefi
|
|
|
1561
1626
|
return undefined;
|
|
1562
1627
|
}
|
|
1563
1628
|
|
|
1629
|
+
function setAnyProperty(propName: string, value: any, attrSpec: AttributeSpec): AttributeSpec {
|
|
1630
|
+
if (attrSpec.properties == undefined) {
|
|
1631
|
+
attrSpec.properties = new Map();
|
|
1632
|
+
}
|
|
1633
|
+
attrSpec.properties.set(propName, value);
|
|
1634
|
+
return attrSpec;
|
|
1635
|
+
}
|
|
1636
|
+
|
|
1564
1637
|
export function isIdAttribute(attrSpec: AttributeSpec): boolean {
|
|
1565
1638
|
return getBooleanProperty('id', attrSpec);
|
|
1566
1639
|
}
|
|
1567
1640
|
|
|
1641
|
+
export function asIdAttribute(attrSpec: AttributeSpec): AttributeSpec {
|
|
1642
|
+
return setAnyProperty('id', true, attrSpec);
|
|
1643
|
+
}
|
|
1644
|
+
|
|
1568
1645
|
export function isUniqueAttribute(attrSpec: AttributeSpec): boolean {
|
|
1569
1646
|
return getBooleanProperty('unique', attrSpec);
|
|
1570
1647
|
}
|
|
1571
1648
|
|
|
1649
|
+
export function asUniqueAttribute(attrSpec: AttributeSpec): AttributeSpec {
|
|
1650
|
+
return setAnyProperty('unique', true, attrSpec);
|
|
1651
|
+
}
|
|
1652
|
+
|
|
1572
1653
|
export function isIndexedAttribute(attrSpec: AttributeSpec): boolean {
|
|
1573
1654
|
return getBooleanProperty('indexed', attrSpec);
|
|
1574
1655
|
}
|
|
1575
1656
|
|
|
1657
|
+
export function asIndexedAttribute(attrSpec: AttributeSpec): AttributeSpec {
|
|
1658
|
+
return setAnyProperty('indexed', true, attrSpec);
|
|
1659
|
+
}
|
|
1660
|
+
|
|
1576
1661
|
export function isOptionalAttribute(attrSpec: AttributeSpec): boolean {
|
|
1577
1662
|
return getBooleanProperty('optional', attrSpec);
|
|
1578
1663
|
}
|
|
1579
1664
|
|
|
1665
|
+
export function asOptionalAttribute(attrSpec: AttributeSpec): AttributeSpec {
|
|
1666
|
+
return setAnyProperty('optional', true, attrSpec);
|
|
1667
|
+
}
|
|
1668
|
+
|
|
1580
1669
|
export function isArrayAttribute(attrSpec: AttributeSpec): boolean {
|
|
1581
1670
|
return getBooleanProperty('array', attrSpec);
|
|
1582
1671
|
}
|
|
@@ -1601,6 +1690,10 @@ export function getAttributeDefaultValue(attrSpec: AttributeSpec): any | undefin
|
|
|
1601
1690
|
return getAnyProperty('default', attrSpec);
|
|
1602
1691
|
}
|
|
1603
1692
|
|
|
1693
|
+
export function setDefaultAttributeValue(attrSpec: AttributeSpec, value: any): AttributeSpec {
|
|
1694
|
+
return setAnyProperty('default', value, attrSpec);
|
|
1695
|
+
}
|
|
1696
|
+
|
|
1604
1697
|
export function getAttributeLength(attrSpec: AttributeSpec): number | undefined {
|
|
1605
1698
|
return getAnyProperty('length', attrSpec);
|
|
1606
1699
|
}
|
|
@@ -2212,12 +2305,14 @@ export class Instance {
|
|
|
2212
2305
|
}
|
|
2213
2306
|
}
|
|
2214
2307
|
|
|
2215
|
-
export function objectAsInstanceAttributes(obj: object): InstanceAttributes {
|
|
2308
|
+
export function objectAsInstanceAttributes(obj: object | undefined): InstanceAttributes {
|
|
2216
2309
|
const attrs: InstanceAttributes = newInstanceAttributes();
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2310
|
+
if (obj) {
|
|
2311
|
+
Object.entries(obj).forEach((v: [string, any]) => {
|
|
2312
|
+
const obj = v[1];
|
|
2313
|
+
attrs.set(v[0], obj);
|
|
2314
|
+
});
|
|
2315
|
+
}
|
|
2221
2316
|
return attrs;
|
|
2222
2317
|
}
|
|
2223
2318
|
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
import { AIMessage, BaseMessage, HumanMessage } from '@langchain/core/messages';
|
|
13
13
|
import { PlannerInstructions } from '../agents/common.js';
|
|
14
14
|
import { PathAttributeNameQuery } from '../defs.js';
|
|
15
|
+
import { logger } from '../logger.js';
|
|
15
16
|
|
|
16
17
|
export const CoreAIModuleName = makeCoreModuleName('ai');
|
|
17
18
|
export const AgentEntityName = 'Agent';
|
|
@@ -28,6 +29,7 @@ entity ${LlmEntityName} {
|
|
|
28
29
|
entity ${AgentEntityName} {
|
|
29
30
|
name String @id,
|
|
30
31
|
type @enum("chat", "planner") @default("chat"),
|
|
32
|
+
runWorkflows Boolean @default(true),
|
|
31
33
|
instruction String @optional,
|
|
32
34
|
tools String @optional, // comma-separated values
|
|
33
35
|
documents String @optional, // comma-separated values
|
|
@@ -67,6 +69,7 @@ export class AgentInstance {
|
|
|
67
69
|
type: string = 'chat';
|
|
68
70
|
tools: string | undefined;
|
|
69
71
|
documents: string | undefined;
|
|
72
|
+
runWorkflows: boolean = true;
|
|
70
73
|
|
|
71
74
|
private constructor() {}
|
|
72
75
|
|
|
@@ -91,21 +94,26 @@ export class AgentInstance {
|
|
|
91
94
|
msgs = [systemMessage(this.instruction)];
|
|
92
95
|
}
|
|
93
96
|
if (msgs) {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
97
|
+
try {
|
|
98
|
+
const sysMsg = msgs[0];
|
|
99
|
+
if (isplnr) {
|
|
100
|
+
const newSysMsg = systemMessage(
|
|
101
|
+
`${PlannerInstructions}\n${this.toolsAsString()}\n${this.instruction}`
|
|
102
|
+
);
|
|
103
|
+
msgs[0] = newSysMsg;
|
|
104
|
+
}
|
|
105
|
+
msgs.push(humanMessage(await this.maybeAddRelevantDocuments(message, env)));
|
|
106
|
+
const response: AIResponse = await p.invoke(msgs);
|
|
107
|
+
msgs.push(assistantMessage(response.content));
|
|
108
|
+
if (isplnr) {
|
|
109
|
+
msgs[0] = sysMsg;
|
|
110
|
+
}
|
|
111
|
+
await saveAgentChatSession(chatId, msgs, env);
|
|
112
|
+
env.setLastResult(response.content);
|
|
113
|
+
} catch (err: any) {
|
|
114
|
+
logger.error(`Error while invoking ${agentName} - ${err}`);
|
|
115
|
+
env.setLastResult(undefined);
|
|
106
116
|
}
|
|
107
|
-
await saveAgentChatSession(chatId, msgs, env);
|
|
108
|
-
env.setLastResult(response.content);
|
|
109
117
|
} else {
|
|
110
118
|
throw new Error(`failed to initialize messages for agent ${agentName}`);
|
|
111
119
|
}
|
|
@@ -130,6 +130,8 @@ entity Session {
|
|
|
130
130
|
id UUID @id,
|
|
131
131
|
userId UUID @indexed,
|
|
132
132
|
authToken String @optional,
|
|
133
|
+
accessToken String @optional,
|
|
134
|
+
refreshToken String @optional,
|
|
133
135
|
isActive Boolean,
|
|
134
136
|
@rbac [(allow: [read, delete, update, create], where: auth.user = this.userId)]
|
|
135
137
|
}
|
|
@@ -137,7 +139,18 @@ entity Session {
|
|
|
137
139
|
|
|
138
140
|
workflow CreateSession {
|
|
139
141
|
{Session {id CreateSession.id, userId CreateSession.userId,
|
|
140
|
-
authToken CreateSession.authToken,
|
|
142
|
+
authToken CreateSession.authToken,
|
|
143
|
+
accessToken CreateSession.accessToken,
|
|
144
|
+
refreshToken CreateSession.refreshToken,
|
|
145
|
+
isActive true}}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
workflow UpdateSession {
|
|
149
|
+
{Session {id? UpdateSession.id,
|
|
150
|
+
authToken UpdateSession.authToken,
|
|
151
|
+
accessToken UpdateSession.accessToken,
|
|
152
|
+
refreshToken UpdateSession.refreshToken,
|
|
153
|
+
isActive true}, @upsert}
|
|
141
154
|
}
|
|
142
155
|
|
|
143
156
|
workflow FindSession {
|
|
@@ -146,7 +159,7 @@ workflow FindSession {
|
|
|
146
159
|
}
|
|
147
160
|
|
|
148
161
|
workflow FindUserSession {
|
|
149
|
-
{Session {userId? FindUserSession.
|
|
162
|
+
{Session {userId? FindUserSession.userId}} as [session];
|
|
150
163
|
session
|
|
151
164
|
}
|
|
152
165
|
|
|
@@ -167,6 +180,18 @@ workflow login {
|
|
|
167
180
|
await Auth.loginUser(login.email, login.password)
|
|
168
181
|
}
|
|
169
182
|
|
|
183
|
+
workflow logout {
|
|
184
|
+
await Auth.logoutUser()
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
workflow changePassword {
|
|
188
|
+
await Auth.changePassword(changePassword.newPassword, changePassword.password)
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
workflow refreshToken {
|
|
192
|
+
await Auth.refreshUserToken(refreshToken.refreshToken)
|
|
193
|
+
}
|
|
194
|
+
|
|
170
195
|
workflow getUser {
|
|
171
196
|
await Auth.getUserInfo(getUser.userId)
|
|
172
197
|
}
|
|
@@ -230,18 +255,32 @@ export async function ensureUser(
|
|
|
230
255
|
return await createUser(crypto.randomUUID(), email, firstName, lastName, env);
|
|
231
256
|
}
|
|
232
257
|
|
|
233
|
-
export async function ensureUserSession(
|
|
258
|
+
export async function ensureUserSession(
|
|
259
|
+
userId: string,
|
|
260
|
+
token: string,
|
|
261
|
+
accessToken: string,
|
|
262
|
+
refreshToken: string,
|
|
263
|
+
env: Environment
|
|
264
|
+
): Promise<Instance> {
|
|
234
265
|
const sess: Instance = await findUserSession(userId, env);
|
|
235
266
|
if (sess) {
|
|
236
|
-
|
|
267
|
+
// Update existing session instead of deleting and recreating
|
|
268
|
+
await updateSession(sess.lookup('id'), token, accessToken, refreshToken, env);
|
|
269
|
+
// Return the updated session by finding it again
|
|
270
|
+
return await findUserSession(userId, env);
|
|
237
271
|
}
|
|
238
|
-
|
|
272
|
+
const sessionId = crypto.randomUUID();
|
|
273
|
+
await createSession(sessionId, userId, token, accessToken, refreshToken, env);
|
|
274
|
+
// Return the created session by finding it
|
|
275
|
+
return await findSession(sessionId, env);
|
|
239
276
|
}
|
|
240
277
|
|
|
241
278
|
export async function createSession(
|
|
242
279
|
id: string,
|
|
243
280
|
userId: string,
|
|
244
281
|
token: string,
|
|
282
|
+
accessToken: string,
|
|
283
|
+
refreshToken: string,
|
|
245
284
|
env: Environment
|
|
246
285
|
): Promise<Result> {
|
|
247
286
|
return await evalEvent(
|
|
@@ -250,6 +289,8 @@ export async function createSession(
|
|
|
250
289
|
id: id,
|
|
251
290
|
userId: userId,
|
|
252
291
|
authToken: token,
|
|
292
|
+
accessToken: accessToken,
|
|
293
|
+
refreshToken: refreshToken,
|
|
253
294
|
},
|
|
254
295
|
env
|
|
255
296
|
);
|
|
@@ -275,6 +316,25 @@ export async function findUserSession(userId: string, env: Environment): Promise
|
|
|
275
316
|
);
|
|
276
317
|
}
|
|
277
318
|
|
|
319
|
+
export async function updateSession(
|
|
320
|
+
id: string,
|
|
321
|
+
token: string,
|
|
322
|
+
accessToken: string,
|
|
323
|
+
refreshToken: string,
|
|
324
|
+
env: Environment
|
|
325
|
+
): Promise<Result> {
|
|
326
|
+
return await evalEvent(
|
|
327
|
+
'UpdateSession',
|
|
328
|
+
{
|
|
329
|
+
id: id,
|
|
330
|
+
authToken: token,
|
|
331
|
+
accessToken: accessToken,
|
|
332
|
+
refreshToken: refreshToken,
|
|
333
|
+
},
|
|
334
|
+
env
|
|
335
|
+
);
|
|
336
|
+
}
|
|
337
|
+
|
|
278
338
|
export async function removeSession(id: string, env: Environment): Promise<Result> {
|
|
279
339
|
return await evalEvent(
|
|
280
340
|
'RemoveSession',
|
|
@@ -539,6 +599,61 @@ export async function loginUser(
|
|
|
539
599
|
}
|
|
540
600
|
}
|
|
541
601
|
|
|
602
|
+
async function logoutSession(userId: string, sess: Instance, env: Environment): Promise<string> {
|
|
603
|
+
const sessId = sess.lookup('id');
|
|
604
|
+
const tok = sess.lookup('authToken');
|
|
605
|
+
await fetchAuthImpl().logout(
|
|
606
|
+
{
|
|
607
|
+
sessionId: sessId,
|
|
608
|
+
userId: userId,
|
|
609
|
+
authToken: tok,
|
|
610
|
+
idToken: tok,
|
|
611
|
+
accessToken: sess.lookup('accessToken'),
|
|
612
|
+
refreshToken: sess.lookup('refreshToken'),
|
|
613
|
+
},
|
|
614
|
+
env
|
|
615
|
+
);
|
|
616
|
+
await removeSession(sessId, env);
|
|
617
|
+
return 'ok';
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
export async function logoutUser(env: Environment): Promise<string | undefined> {
|
|
621
|
+
const user = env.getActiveUser();
|
|
622
|
+
const sess = await findUserSession(user, env);
|
|
623
|
+
if (sess) {
|
|
624
|
+
return await logoutSession(user, sess, env);
|
|
625
|
+
}
|
|
626
|
+
return undefined;
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
export async function changePassword(
|
|
630
|
+
newPassword: string,
|
|
631
|
+
password: string,
|
|
632
|
+
env: Environment
|
|
633
|
+
): Promise<string | undefined> {
|
|
634
|
+
const user = env.getActiveUser();
|
|
635
|
+
const sess = await findUserSession(user, env);
|
|
636
|
+
if (sess) {
|
|
637
|
+
const sessId = sess.lookup('id');
|
|
638
|
+
const tok = sess.lookup('authToken');
|
|
639
|
+
const sessInfo = {
|
|
640
|
+
sessionId: sessId,
|
|
641
|
+
userId: user,
|
|
642
|
+
authToken: tok,
|
|
643
|
+
idToken: tok,
|
|
644
|
+
accessToken: sess.lookup('accessToken'),
|
|
645
|
+
refreshToken: sess.lookup('refreshToken'),
|
|
646
|
+
};
|
|
647
|
+
if (await fetchAuthImpl().changePassword(sessInfo, newPassword, password, env)) {
|
|
648
|
+
return await logoutSession(user, sess, env);
|
|
649
|
+
} else {
|
|
650
|
+
return undefined;
|
|
651
|
+
}
|
|
652
|
+
} else {
|
|
653
|
+
throw new UnauthorisedError(`No active session for user ${user}`);
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
|
|
542
657
|
export async function verifySession(token: string, env?: Environment): Promise<ActiveSessionInfo> {
|
|
543
658
|
if (!isAuthEnabled()) return BypassSession;
|
|
544
659
|
|
|
@@ -598,9 +713,12 @@ async function verifyJwtToken(token: string, env?: Environment): Promise<ActiveS
|
|
|
598
713
|
|
|
599
714
|
// Use the local user's ID for consistency
|
|
600
715
|
const localUserId = localUser.lookup('id');
|
|
601
|
-
|
|
716
|
+
const sess = await findUserSession(localUserId, env);
|
|
717
|
+
if (!sess) {
|
|
718
|
+
throw new UnauthorisedError(`No session found for user ${email}, UserId: ${userId}`);
|
|
719
|
+
}
|
|
602
720
|
// For JWT tokens, we use the token itself as sessionId for tracking
|
|
603
|
-
return { sessionId:
|
|
721
|
+
return { sessionId: sess.lookup('id'), userId: localUserId };
|
|
604
722
|
} catch (err: any) {
|
|
605
723
|
if (err instanceof UnauthorisedError) {
|
|
606
724
|
throw err;
|
|
@@ -690,8 +808,38 @@ export async function getUserInfoByEmail(email: string, env: Environment): Promi
|
|
|
690
808
|
}
|
|
691
809
|
}
|
|
692
810
|
|
|
811
|
+
export async function refreshUserToken(refreshToken: string, env: Environment): Promise<object> {
|
|
812
|
+
const needCommit = env ? false : true;
|
|
813
|
+
env = env ? env : new Environment();
|
|
814
|
+
const f = async () => {
|
|
815
|
+
try {
|
|
816
|
+
const sessionInfo = await fetchAuthImpl().refreshToken(refreshToken, env);
|
|
817
|
+
|
|
818
|
+
return {
|
|
819
|
+
id_token: sessionInfo.idToken,
|
|
820
|
+
access_token: sessionInfo.accessToken,
|
|
821
|
+
refresh_token: sessionInfo.refreshToken,
|
|
822
|
+
token_type: 'Bearer',
|
|
823
|
+
expires_in: 3600,
|
|
824
|
+
userId: sessionInfo.userId,
|
|
825
|
+
sessionId: sessionInfo.sessionId,
|
|
826
|
+
};
|
|
827
|
+
} catch (err: any) {
|
|
828
|
+
logger.error(`Token refresh failed: ${err.message}`);
|
|
829
|
+
throw err;
|
|
830
|
+
}
|
|
831
|
+
};
|
|
832
|
+
if (needCommit) {
|
|
833
|
+
return await env.callInTransaction(f);
|
|
834
|
+
} else {
|
|
835
|
+
return await f();
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
|
|
693
839
|
export function requireAuth(moduleName: string, eventName: string): boolean {
|
|
694
|
-
const f =
|
|
840
|
+
const f =
|
|
841
|
+
moduleName == CoreAuthModuleName &&
|
|
842
|
+
(eventName == 'login' || eventName == 'signup' || eventName == 'refreshToken');
|
|
695
843
|
return !f;
|
|
696
844
|
}
|
|
697
845
|
|
|
@@ -40,6 +40,7 @@ import { Environment } from '../../interpreter.js';
|
|
|
40
40
|
import { OpenAIEmbeddings } from '@langchain/openai';
|
|
41
41
|
import { Embeddings } from '@langchain/core/embeddings';
|
|
42
42
|
import { DeletedFlagAttributeName, ParentAttributeName, PathAttributeName } from '../../defs.js';
|
|
43
|
+
import { logger } from '../../logger.js';
|
|
43
44
|
|
|
44
45
|
function maybeFindIdAttributeName(inst: Instance): string | undefined {
|
|
45
46
|
const attrEntry: AttributeEntry | undefined = findIdAttribute(inst);
|
|
@@ -108,9 +109,13 @@ export class SqlDbResolver extends Resolver {
|
|
|
108
109
|
await insertRow(n, rowObj, ctx, orUpdate);
|
|
109
110
|
if (inst.record.getFullTextSearchAttributes()) {
|
|
110
111
|
const path = attrs.get(PathAttributeName);
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
112
|
+
try {
|
|
113
|
+
if (!(await vectorStoreSearchEntryExists(n, path, ctx))) {
|
|
114
|
+
const res = await this.embeddings.embedQuery(JSON.stringify(rowObj));
|
|
115
|
+
await addRowForFullTextSearch(n, path, res, ctx);
|
|
116
|
+
}
|
|
117
|
+
} catch (reason: any) {
|
|
118
|
+
logger.warn(`Full text indexing failed for ${path} - ${reason}`);
|
|
114
119
|
}
|
|
115
120
|
}
|
|
116
121
|
return inst;
|
package/src/runtime/util.ts
CHANGED
|
@@ -11,7 +11,6 @@ import {
|
|
|
11
11
|
Statement,
|
|
12
12
|
} from '../language/generated/ast.js';
|
|
13
13
|
import { readFile } from '../utils/fs-utils.js';
|
|
14
|
-
import { logger } from './logger.js';
|
|
15
14
|
|
|
16
15
|
export const QuerySuffix = '?';
|
|
17
16
|
|
|
@@ -27,75 +26,6 @@ if (isNodeEnv) {
|
|
|
27
26
|
promisify = nu.promisify;
|
|
28
27
|
}
|
|
29
28
|
|
|
30
|
-
const importedModules = new Map<string, any>();
|
|
31
|
-
|
|
32
|
-
// Usage: importModule("./mymodels/acme.js")
|
|
33
|
-
export async function importModule(path: string, name: string) {
|
|
34
|
-
const m = await import(/* @vite-ignore */ path);
|
|
35
|
-
importedModules.set(name, m);
|
|
36
|
-
// e.g of dynamic fn-call:
|
|
37
|
-
//// let f = eval("(a, b) => m.add(a, b)");
|
|
38
|
-
//// console.log(f(10, 20))
|
|
39
|
-
return m;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export function moduleImported(moduleName: string): boolean {
|
|
43
|
-
return importedModules.has(moduleName);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
function maybeEvalFunction(fnName: string): Function | undefined {
|
|
47
|
-
try {
|
|
48
|
-
return eval(fnName);
|
|
49
|
-
} catch (reason: any) {
|
|
50
|
-
logger.debug(reason);
|
|
51
|
-
return undefined;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export async function invokeModuleFn(
|
|
56
|
-
fqFnName: string,
|
|
57
|
-
args: Array<any> | null,
|
|
58
|
-
isAsync: boolean = false
|
|
59
|
-
): Promise<any> {
|
|
60
|
-
try {
|
|
61
|
-
const refs: string[] = splitRefs(fqFnName);
|
|
62
|
-
const m = importedModules.get(refs[0]);
|
|
63
|
-
if (m != undefined) {
|
|
64
|
-
const f = m[refs[1]];
|
|
65
|
-
if (f != undefined) {
|
|
66
|
-
if (args == null)
|
|
67
|
-
if (isAsync) {
|
|
68
|
-
return await f();
|
|
69
|
-
} else return f();
|
|
70
|
-
else if (isAsync) {
|
|
71
|
-
return await f(...args);
|
|
72
|
-
} else return f(...args);
|
|
73
|
-
} else throw new Error(`Function not found - ${fqFnName}`);
|
|
74
|
-
} else throw new Error(`JavaScript module ${refs[0]} not found`);
|
|
75
|
-
} catch (reason: any) {
|
|
76
|
-
const pf: Function | undefined = maybeEvalFunction(fqFnName);
|
|
77
|
-
if (pf instanceof Function) {
|
|
78
|
-
if (args == null) {
|
|
79
|
-
if (isAsync) return await pf();
|
|
80
|
-
else return pf();
|
|
81
|
-
} else {
|
|
82
|
-
if (isAsync) return await pf(...args.slice(0, args.length - 1));
|
|
83
|
-
else return pf(...args.slice(0, args.length - 1));
|
|
84
|
-
}
|
|
85
|
-
} else {
|
|
86
|
-
throw new Error(reason);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
export function getModuleFn(fqFnName: string): Function | undefined {
|
|
92
|
-
const refs: string[] = splitRefs(fqFnName);
|
|
93
|
-
const m = importedModules.get(refs[0]);
|
|
94
|
-
if (m != undefined) {
|
|
95
|
-
return m[refs[1]];
|
|
96
|
-
} else return undefined;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
29
|
export function isNumber(x: any): boolean {
|
|
100
30
|
return typeof x === 'number';
|
|
101
31
|
}
|