agentlang 0.7.9 → 0.7.11
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/api/http.d.ts.map +1 -1
- package/out/api/http.js +8 -1
- package/out/api/http.js.map +1 -1
- package/out/cli/main.d.ts.map +1 -1
- package/out/cli/main.js +33 -2
- package/out/cli/main.js.map +1 -1
- package/out/extension/main.cjs +250 -250
- package/out/extension/main.cjs.map +2 -2
- package/out/language/agentlang-validator.d.ts +1 -2
- package/out/language/agentlang-validator.d.ts.map +1 -1
- package/out/language/agentlang-validator.js +0 -39
- package/out/language/agentlang-validator.js.map +1 -1
- package/out/language/generated/ast.d.ts +62 -11
- package/out/language/generated/ast.d.ts.map +1 -1
- package/out/language/generated/ast.js +75 -3
- package/out/language/generated/ast.js.map +1 -1
- package/out/language/generated/grammar.d.ts.map +1 -1
- package/out/language/generated/grammar.js +758 -239
- package/out/language/generated/grammar.js.map +1 -1
- package/out/language/main.cjs +1370 -824
- package/out/language/main.cjs.map +4 -4
- package/out/language/parser.d.ts +1 -0
- package/out/language/parser.d.ts.map +1 -1
- package/out/language/parser.js +44 -7
- package/out/language/parser.js.map +1 -1
- package/out/language/syntax.d.ts +1 -1
- package/out/language/syntax.d.ts.map +1 -1
- package/out/language/syntax.js +22 -13
- package/out/language/syntax.js.map +1 -1
- package/out/runtime/api.d.ts +2 -0
- package/out/runtime/api.d.ts.map +1 -1
- package/out/runtime/api.js +5 -0
- package/out/runtime/api.js.map +1 -1
- package/out/runtime/auth/cognito.d.ts.map +1 -1
- package/out/runtime/auth/cognito.js +4 -4
- package/out/runtime/auth/cognito.js.map +1 -1
- package/out/runtime/defs.d.ts +5 -0
- package/out/runtime/defs.d.ts.map +1 -1
- package/out/runtime/defs.js +16 -0
- package/out/runtime/defs.js.map +1 -1
- package/out/runtime/exec-graph.js +1 -1
- package/out/runtime/exec-graph.js.map +1 -1
- package/out/runtime/interpreter.d.ts +6 -1
- package/out/runtime/interpreter.d.ts.map +1 -1
- package/out/runtime/interpreter.js +144 -112
- package/out/runtime/interpreter.js.map +1 -1
- package/out/runtime/loader.d.ts +1 -1
- package/out/runtime/loader.d.ts.map +1 -1
- package/out/runtime/loader.js +74 -27
- package/out/runtime/loader.js.map +1 -1
- package/out/runtime/module.d.ts +41 -11
- package/out/runtime/module.d.ts.map +1 -1
- package/out/runtime/module.js +238 -50
- package/out/runtime/module.js.map +1 -1
- package/out/runtime/modules/ai.d.ts.map +1 -1
- package/out/runtime/modules/ai.js +13 -6
- package/out/runtime/modules/ai.js.map +1 -1
- package/out/runtime/modules/auth.d.ts +2 -1
- package/out/runtime/modules/auth.d.ts.map +1 -1
- package/out/runtime/modules/auth.js +93 -3
- package/out/runtime/modules/auth.js.map +1 -1
- package/out/runtime/modules/core.d.ts +7 -5
- package/out/runtime/modules/core.d.ts.map +1 -1
- package/out/runtime/modules/core.js +93 -16
- package/out/runtime/modules/core.js.map +1 -1
- package/out/runtime/monitor.d.ts.map +1 -1
- package/out/runtime/monitor.js +1 -0
- package/out/runtime/monitor.js.map +1 -1
- package/out/runtime/resolvers/interface.d.ts +6 -1
- package/out/runtime/resolvers/interface.d.ts.map +1 -1
- package/out/runtime/resolvers/interface.js +2 -2
- package/out/runtime/resolvers/interface.js.map +1 -1
- package/out/runtime/resolvers/sqldb/database.d.ts +19 -2
- package/out/runtime/resolvers/sqldb/database.d.ts.map +1 -1
- package/out/runtime/resolvers/sqldb/database.js +107 -21
- package/out/runtime/resolvers/sqldb/database.js.map +1 -1
- package/out/runtime/resolvers/sqldb/dbutil.d.ts +1 -0
- package/out/runtime/resolvers/sqldb/dbutil.d.ts.map +1 -1
- package/out/runtime/resolvers/sqldb/dbutil.js +25 -3
- package/out/runtime/resolvers/sqldb/dbutil.js.map +1 -1
- package/out/runtime/resolvers/sqldb/impl.d.ts +3 -2
- package/out/runtime/resolvers/sqldb/impl.d.ts.map +1 -1
- package/out/runtime/resolvers/sqldb/impl.js +80 -6
- package/out/runtime/resolvers/sqldb/impl.js.map +1 -1
- package/out/runtime/state.d.ts +58 -0
- package/out/runtime/state.d.ts.map +1 -1
- package/out/runtime/state.js +12 -0
- package/out/runtime/state.js.map +1 -1
- package/out/runtime/util.d.ts +1 -1
- package/out/runtime/util.d.ts.map +1 -1
- package/out/runtime/util.js +27 -13
- package/out/runtime/util.js.map +1 -1
- package/out/setupClassic.d.ts +98 -0
- package/out/setupClassic.d.ts.map +1 -0
- package/out/setupClassic.js +38 -0
- package/out/setupClassic.js.map +1 -0
- package/out/setupCommon.d.ts +2 -0
- package/out/setupCommon.d.ts.map +1 -0
- package/out/setupCommon.js +33 -0
- package/out/setupCommon.js.map +1 -0
- package/out/setupExtended.d.ts +40 -0
- package/out/setupExtended.d.ts.map +1 -0
- package/out/setupExtended.js +67 -0
- package/out/setupExtended.js.map +1 -0
- package/out/syntaxes/agentlang.monarch.js +1 -1
- package/out/syntaxes/agentlang.monarch.js.map +1 -1
- package/package.json +187 -185
- package/src/api/http.ts +8 -0
- package/src/cli/main.ts +38 -2
- package/src/language/agentlang-validator.ts +1 -51
- package/src/language/agentlang.langium +17 -4
- package/src/language/generated/ast.ts +147 -13
- package/src/language/generated/grammar.ts +758 -239
- package/src/language/parser.ts +43 -8
- package/src/language/syntax.ts +25 -12
- package/src/runtime/api.ts +8 -0
- package/src/runtime/defs.ts +8 -0
- package/src/runtime/interpreter.ts +104 -76
- package/src/runtime/loader.ts +75 -25
- package/src/runtime/module.ts +194 -32
- package/src/runtime/modules/ai.ts +10 -4
- package/src/runtime/modules/auth.ts +1 -0
- package/src/runtime/modules/core.ts +99 -23
- package/src/runtime/monitor.ts +1 -0
- package/src/runtime/resolvers/interface.ts +9 -2
- package/src/runtime/resolvers/sqldb/database.ts +68 -17
- package/src/runtime/resolvers/sqldb/dbutil.ts +28 -6
- package/src/runtime/resolvers/sqldb/impl.ts +86 -14
- package/src/runtime/state.ts +14 -0
- package/src/runtime/util.ts +25 -12
- package/src/syntaxes/agentlang.monarch.ts +1 -1
package/src/runtime/module.ts
CHANGED
|
@@ -20,6 +20,8 @@ import {
|
|
|
20
20
|
RbacSpecEntries,
|
|
21
21
|
RbacOpr,
|
|
22
22
|
WorkflowHeader,
|
|
23
|
+
FlowDefinition,
|
|
24
|
+
FlowEntry,
|
|
23
25
|
} from '../language/generated/ast.js';
|
|
24
26
|
import {
|
|
25
27
|
Path,
|
|
@@ -75,7 +77,7 @@ import {
|
|
|
75
77
|
removeAgentResponseSchema,
|
|
76
78
|
removeAgentScenarios,
|
|
77
79
|
} from './agents/common.js';
|
|
78
|
-
import { Environment } from './interpreter.js';
|
|
80
|
+
import { AggregateFunctionCall, Environment } from './interpreter.js';
|
|
79
81
|
import { isNode } from '../utils/fs-utils.js';
|
|
80
82
|
|
|
81
83
|
export class ModuleEntry {
|
|
@@ -208,7 +210,7 @@ function attributePropertyValueToString(
|
|
|
208
210
|
});
|
|
209
211
|
return ss.join(',');
|
|
210
212
|
} else if (propName == 'default') {
|
|
211
|
-
if (isTextualType(attrType) &&
|
|
213
|
+
if (isTextualType(attrType) && !defaultValueIsFunctionCall(propValue)) {
|
|
212
214
|
return `"${propValue}"`;
|
|
213
215
|
}
|
|
214
216
|
} else if (propName == 'comment') {
|
|
@@ -433,6 +435,37 @@ export class Record extends ModuleEntry {
|
|
|
433
435
|
return this;
|
|
434
436
|
}
|
|
435
437
|
|
|
438
|
+
public getSecretAttributes(): Array<string> {
|
|
439
|
+
const result = new Array<string>();
|
|
440
|
+
this.schema.forEach((spec: AttributeSpec, n: string) => {
|
|
441
|
+
if (spec.properties?.get('secret') === true) {
|
|
442
|
+
result.push(n);
|
|
443
|
+
}
|
|
444
|
+
});
|
|
445
|
+
return result;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
private static WriteOnlyAttributes = new Map<string, Array<string>>();
|
|
449
|
+
|
|
450
|
+
public getWriteOnlyAttributes(): Array<string> | undefined {
|
|
451
|
+
const fqn = this.getFqName();
|
|
452
|
+
const cachedResult = Record.WriteOnlyAttributes.get(fqn);
|
|
453
|
+
if (cachedResult !== undefined) {
|
|
454
|
+
if (cachedResult.length === 0) return undefined;
|
|
455
|
+
return cachedResult;
|
|
456
|
+
} else {
|
|
457
|
+
const result = new Array<string>();
|
|
458
|
+
this.schema.forEach((spec: AttributeSpec, n: string) => {
|
|
459
|
+
if (spec.properties?.get('writeonly') === true) {
|
|
460
|
+
result.push(n);
|
|
461
|
+
}
|
|
462
|
+
});
|
|
463
|
+
const finalResult = result.concat(this.getSecretAttributes());
|
|
464
|
+
Record.WriteOnlyAttributes.set(fqn, finalResult);
|
|
465
|
+
return finalResult;
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
|
|
436
469
|
getCompositeUniqueAttributes(): Array<string> | undefined {
|
|
437
470
|
return this.compositeUqAttributes;
|
|
438
471
|
}
|
|
@@ -641,18 +674,27 @@ export class Record extends ModuleEntry {
|
|
|
641
674
|
return s.concat('\n{', scms, '\n}\n');
|
|
642
675
|
}
|
|
643
676
|
|
|
677
|
+
private userAttrsSchema: RecordSchema | undefined;
|
|
678
|
+
|
|
644
679
|
getUserAttributes(): RecordSchema {
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
680
|
+
if (this.userAttrsSchema === undefined) {
|
|
681
|
+
this.userAttrsSchema = newRecordSchema();
|
|
682
|
+
this.schema.forEach((attrSpec: AttributeSpec, n: string) => {
|
|
683
|
+
if (!isSystemAttribute(attrSpec)) {
|
|
684
|
+
this.userAttrsSchema?.set(n, attrSpec);
|
|
685
|
+
}
|
|
686
|
+
});
|
|
687
|
+
}
|
|
688
|
+
return this.userAttrsSchema;
|
|
652
689
|
}
|
|
653
690
|
|
|
654
|
-
|
|
655
|
-
|
|
691
|
+
private userAttrNames: Set<string> | undefined;
|
|
692
|
+
|
|
693
|
+
getUserAttributeNames(): Set<string> {
|
|
694
|
+
if (this.userAttrNames === undefined) {
|
|
695
|
+
this.userAttrNames = new Set([...this.getUserAttributes().keys()]);
|
|
696
|
+
}
|
|
697
|
+
return this.userAttrNames;
|
|
656
698
|
}
|
|
657
699
|
}
|
|
658
700
|
|
|
@@ -1592,18 +1634,21 @@ export type FlowGraphNode = {
|
|
|
1592
1634
|
next: string[];
|
|
1593
1635
|
};
|
|
1594
1636
|
|
|
1637
|
+
function splitFlowSteps(flow: FlowDefinition): string[] {
|
|
1638
|
+
const steps = new Array<string>();
|
|
1639
|
+
flow.body?.entries.forEach((fe: FlowEntry) => {
|
|
1640
|
+
steps.push(fe.$cstNode?.text || '');
|
|
1641
|
+
});
|
|
1642
|
+
return steps;
|
|
1643
|
+
}
|
|
1644
|
+
|
|
1595
1645
|
export class Flow extends ModuleEntry {
|
|
1596
1646
|
flowSteps: string[];
|
|
1597
1647
|
|
|
1598
|
-
constructor(name: string, moduleName: string, flow?:
|
|
1648
|
+
constructor(name: string, moduleName: string, flow?: FlowDefinition) {
|
|
1599
1649
|
super(name, moduleName);
|
|
1600
|
-
this.flowSteps =
|
|
1601
|
-
|
|
1602
|
-
const s = step.trim();
|
|
1603
|
-
if (s.length > 0) {
|
|
1604
|
-
this.flowSteps.push(s);
|
|
1605
|
-
}
|
|
1606
|
-
});
|
|
1650
|
+
if (flow) this.flowSteps = splitFlowSteps(flow);
|
|
1651
|
+
else this.flowSteps = new Array<string>();
|
|
1607
1652
|
}
|
|
1608
1653
|
|
|
1609
1654
|
getFlow(): string {
|
|
@@ -1629,10 +1674,11 @@ export class Flow extends ModuleEntry {
|
|
|
1629
1674
|
return this.flowSteps.length;
|
|
1630
1675
|
}
|
|
1631
1676
|
|
|
1632
|
-
toGraph(): FlowGraphNode[] {
|
|
1677
|
+
async toGraph(): Promise<FlowGraphNode[]> {
|
|
1633
1678
|
const result = new Array<FlowGraphNode>();
|
|
1634
|
-
this.flowSteps.
|
|
1635
|
-
const
|
|
1679
|
+
for (let i = 0; i < this.flowSteps.length; ++i) {
|
|
1680
|
+
const s = this.flowSteps[i];
|
|
1681
|
+
const fp = await FlowStepPattern.Parse(s);
|
|
1636
1682
|
if (fp.condition) {
|
|
1637
1683
|
const orig = result.find((v: FlowGraphNode) => {
|
|
1638
1684
|
return v.label == fp.first;
|
|
@@ -1657,7 +1703,7 @@ export class Flow extends ModuleEntry {
|
|
|
1657
1703
|
next: [fp.next],
|
|
1658
1704
|
});
|
|
1659
1705
|
}
|
|
1660
|
-
}
|
|
1706
|
+
}
|
|
1661
1707
|
return result;
|
|
1662
1708
|
}
|
|
1663
1709
|
|
|
@@ -1801,6 +1847,11 @@ export class Retry extends ModuleEntry {
|
|
|
1801
1847
|
};
|
|
1802
1848
|
}
|
|
1803
1849
|
|
|
1850
|
+
setBackoffStrategy(s: BackoffStrategy): Retry {
|
|
1851
|
+
this.backoff.strategy = s;
|
|
1852
|
+
return this;
|
|
1853
|
+
}
|
|
1854
|
+
|
|
1804
1855
|
setExponentialBackoff(): Retry {
|
|
1805
1856
|
this.backoff.strategy = 'e';
|
|
1806
1857
|
return this;
|
|
@@ -1835,6 +1886,17 @@ export class Retry extends ModuleEntry {
|
|
|
1835
1886
|
return this;
|
|
1836
1887
|
}
|
|
1837
1888
|
|
|
1889
|
+
setBackoffMagnitude(m: string): Retry {
|
|
1890
|
+
if (m[0] === 's') {
|
|
1891
|
+
this.backoff.magnitude = 's';
|
|
1892
|
+
} else if (m.startsWith('milli')) {
|
|
1893
|
+
this.backoff.magnitude = 'ms';
|
|
1894
|
+
} else {
|
|
1895
|
+
this.backoff.magnitude = 'm';
|
|
1896
|
+
}
|
|
1897
|
+
return this;
|
|
1898
|
+
}
|
|
1899
|
+
|
|
1838
1900
|
setBackoffMagnitudeAsMilliseconds(): Retry {
|
|
1839
1901
|
this.backoff.magnitude = 'ms';
|
|
1840
1902
|
return this;
|
|
@@ -1995,9 +2057,15 @@ export function isEmptyWorkflow(wf: Workflow): boolean {
|
|
|
1995
2057
|
return wf == EmptyWorkflow;
|
|
1996
2058
|
}
|
|
1997
2059
|
|
|
2060
|
+
export type ModuleImportEntry = {
|
|
2061
|
+
path: string;
|
|
2062
|
+
name: string;
|
|
2063
|
+
};
|
|
2064
|
+
|
|
1998
2065
|
export class Module {
|
|
1999
2066
|
name: string;
|
|
2000
2067
|
entries: ModuleEntry[];
|
|
2068
|
+
imports: ModuleImportEntry[] | undefined;
|
|
2001
2069
|
|
|
2002
2070
|
constructor(name: string) {
|
|
2003
2071
|
this.name = name;
|
|
@@ -2009,6 +2077,21 @@ export class Module {
|
|
|
2009
2077
|
return entry;
|
|
2010
2078
|
}
|
|
2011
2079
|
|
|
2080
|
+
addImport(entry: ModuleImportEntry): Module {
|
|
2081
|
+
if (this.imports === undefined) {
|
|
2082
|
+
this.imports = new Array<ModuleImportEntry>();
|
|
2083
|
+
}
|
|
2084
|
+
this.imports?.push(entry);
|
|
2085
|
+
return this;
|
|
2086
|
+
}
|
|
2087
|
+
|
|
2088
|
+
removeImportAt(index: number): Module {
|
|
2089
|
+
if (index >= 0) {
|
|
2090
|
+
this.imports?.splice(index, 1);
|
|
2091
|
+
}
|
|
2092
|
+
return this;
|
|
2093
|
+
}
|
|
2094
|
+
|
|
2012
2095
|
getConfigEntity(): Entity | undefined {
|
|
2013
2096
|
return this.getEntityEntries().find((e: Entity) => {
|
|
2014
2097
|
return e.isConfigEntity();
|
|
@@ -2031,8 +2114,8 @@ export class Module {
|
|
|
2031
2114
|
return this.removeEntry(Agent.EscapeName(agentName));
|
|
2032
2115
|
}
|
|
2033
2116
|
|
|
2034
|
-
addFlow(name: string,
|
|
2035
|
-
const flow: Flow = new Flow(Flow.asFlowName(name), this.name,
|
|
2117
|
+
addFlow(name: string, flowDef?: FlowDefinition): Flow {
|
|
2118
|
+
const flow: Flow = new Flow(Flow.asFlowName(name), this.name, flowDef);
|
|
2036
2119
|
this.addEntry(flow);
|
|
2037
2120
|
return flow;
|
|
2038
2121
|
}
|
|
@@ -2434,6 +2517,14 @@ export class Module {
|
|
|
2434
2517
|
return names;
|
|
2435
2518
|
}
|
|
2436
2519
|
|
|
2520
|
+
getBetweenRelationshipNames(): string[] {
|
|
2521
|
+
const names: string[] = [];
|
|
2522
|
+
this.getRelationshipEntries().forEach((re: Relationship) => {
|
|
2523
|
+
if (re.isBetween()) names.push(re.name);
|
|
2524
|
+
});
|
|
2525
|
+
return names;
|
|
2526
|
+
}
|
|
2527
|
+
|
|
2437
2528
|
isContainsRelationship(entryName: string): boolean {
|
|
2438
2529
|
if (this.hasEntry(entryName)) {
|
|
2439
2530
|
const entry: ModuleEntry = this.getEntry(entryName);
|
|
@@ -2450,6 +2541,17 @@ export class Module {
|
|
|
2450
2541
|
return false;
|
|
2451
2542
|
}
|
|
2452
2543
|
|
|
2544
|
+
private importsAsString(): string {
|
|
2545
|
+
if (this.imports !== undefined) {
|
|
2546
|
+
const ss = new Array<string>();
|
|
2547
|
+
this.imports.forEach((me: ModuleImportEntry) => {
|
|
2548
|
+
ss.push(`import "${me.path}" @as ${me.name}`);
|
|
2549
|
+
});
|
|
2550
|
+
return `\n${ss.join('\n')}\n`;
|
|
2551
|
+
}
|
|
2552
|
+
return '';
|
|
2553
|
+
}
|
|
2554
|
+
|
|
2453
2555
|
toString(): string {
|
|
2454
2556
|
const ss: Array<string> = [];
|
|
2455
2557
|
this.entries.forEach((me: ModuleEntry) => {
|
|
@@ -2458,8 +2560,27 @@ export class Module {
|
|
|
2458
2560
|
}
|
|
2459
2561
|
ss.push(me.toString());
|
|
2460
2562
|
});
|
|
2461
|
-
return `module ${this.name}\n\n${ss.join('\n')}`;
|
|
2563
|
+
return `module ${this.name}\n${this.importsAsString()}\n${ss.join('\n')}`;
|
|
2564
|
+
}
|
|
2565
|
+
}
|
|
2566
|
+
|
|
2567
|
+
let GlobalRetries: Array<Retry> | undefined = undefined;
|
|
2568
|
+
|
|
2569
|
+
export function addGlobalRetry(r: Retry): Retry {
|
|
2570
|
+
if (GlobalRetries === undefined) {
|
|
2571
|
+
GlobalRetries = new Array<Retry>();
|
|
2572
|
+
}
|
|
2573
|
+
GlobalRetries?.push(r);
|
|
2574
|
+
return r;
|
|
2575
|
+
}
|
|
2576
|
+
|
|
2577
|
+
export function getGlobalRetry(name: string): Retry | undefined {
|
|
2578
|
+
if (GlobalRetries !== undefined) {
|
|
2579
|
+
return GlobalRetries.find((r: Retry) => {
|
|
2580
|
+
return r.name === name;
|
|
2581
|
+
});
|
|
2462
2582
|
}
|
|
2583
|
+
return undefined;
|
|
2463
2584
|
}
|
|
2464
2585
|
|
|
2465
2586
|
declare global {
|
|
@@ -2587,6 +2708,8 @@ export const propertyNames = new Set([
|
|
|
2587
2708
|
'@fk',
|
|
2588
2709
|
'@ref',
|
|
2589
2710
|
'@readonly',
|
|
2711
|
+
'@writeonly',
|
|
2712
|
+
'@secret',
|
|
2590
2713
|
'@enum',
|
|
2591
2714
|
'@oneof',
|
|
2592
2715
|
'@comment',
|
|
@@ -2655,7 +2778,7 @@ export function defaultAttributes(schema: RecordSchema): Map<string, any> {
|
|
|
2655
2778
|
export function passwordAttributes(schema: RecordSchema): Set<string> | undefined {
|
|
2656
2779
|
let result: Set<string> | undefined = undefined;
|
|
2657
2780
|
schema.forEach((v: AttributeSpec, k: string) => {
|
|
2658
|
-
if (v.type == 'Password') {
|
|
2781
|
+
if (v.type == 'Password' || v.properties?.get('secret') === true) {
|
|
2659
2782
|
if (result === undefined) {
|
|
2660
2783
|
result = new Set<string>();
|
|
2661
2784
|
}
|
|
@@ -3336,6 +3459,10 @@ export class Instance {
|
|
|
3336
3459
|
queryAttributes: InstanceAttributes | undefined;
|
|
3337
3460
|
queryAttributeValues: InstanceAttributes | undefined;
|
|
3338
3461
|
relatedInstances: Map<string, Instance[]> | undefined;
|
|
3462
|
+
aggregates: Map<string, AggregateFunctionCall> | undefined;
|
|
3463
|
+
groupBy: string[] | undefined;
|
|
3464
|
+
orderBy: string[] | undefined;
|
|
3465
|
+
orderByDesc: boolean = false;
|
|
3339
3466
|
private contextData: Map<string, any> | undefined;
|
|
3340
3467
|
private ___id: string;
|
|
3341
3468
|
|
|
@@ -3432,6 +3559,22 @@ export class Instance {
|
|
|
3432
3559
|
return this.lookup(PathAttributeName);
|
|
3433
3560
|
}
|
|
3434
3561
|
|
|
3562
|
+
setAggregates(aggregates: Map<string, AggregateFunctionCall>): Instance {
|
|
3563
|
+
this.aggregates = aggregates;
|
|
3564
|
+
return this;
|
|
3565
|
+
}
|
|
3566
|
+
|
|
3567
|
+
setGroupBy(n: string[]): Instance {
|
|
3568
|
+
this.groupBy = n;
|
|
3569
|
+
return this;
|
|
3570
|
+
}
|
|
3571
|
+
|
|
3572
|
+
setOrderBy(n: string[], desc: boolean = false): Instance {
|
|
3573
|
+
this.orderBy = n;
|
|
3574
|
+
this.orderByDesc = desc;
|
|
3575
|
+
return this;
|
|
3576
|
+
}
|
|
3577
|
+
|
|
3435
3578
|
asSerializableObject(): object {
|
|
3436
3579
|
const obj: any = {
|
|
3437
3580
|
AL_INSTANCE: true,
|
|
@@ -3519,6 +3662,15 @@ export class Instance {
|
|
|
3519
3662
|
return Object.fromEntries(attrs);
|
|
3520
3663
|
}
|
|
3521
3664
|
|
|
3665
|
+
userAttributesAsObject(forSerialization: boolean = false): object {
|
|
3666
|
+
const attrs = newInstanceAttributes();
|
|
3667
|
+
const userAttrNames = this.getAllUserAttributeNames();
|
|
3668
|
+
this.attributes.forEach((v: any, k: string) => {
|
|
3669
|
+
if (userAttrNames.has(k)) attrs.set(k, Instance.asSerializableValue(v, forSerialization));
|
|
3670
|
+
});
|
|
3671
|
+
return Object.fromEntries(attrs);
|
|
3672
|
+
}
|
|
3673
|
+
|
|
3522
3674
|
static stringifyObjects(attributes: InstanceAttributes): object {
|
|
3523
3675
|
const attrs = newInstanceAttributes();
|
|
3524
3676
|
attributes.forEach((v: any, k: string) => {
|
|
@@ -3549,6 +3701,10 @@ export class Instance {
|
|
|
3549
3701
|
return {};
|
|
3550
3702
|
}
|
|
3551
3703
|
|
|
3704
|
+
getQueryValue(k: string): any {
|
|
3705
|
+
return this.queryAttributeValues?.get(k);
|
|
3706
|
+
}
|
|
3707
|
+
|
|
3552
3708
|
addQuery(attrName: string, op: string = '=', attrVal: any = undefined) {
|
|
3553
3709
|
if (this.queryAttributes === undefined) this.queryAttributes = newInstanceAttributes();
|
|
3554
3710
|
this.queryAttributes.set(attrName, op);
|
|
@@ -3610,7 +3766,7 @@ export class Instance {
|
|
|
3610
3766
|
return undefined;
|
|
3611
3767
|
}
|
|
3612
3768
|
|
|
3613
|
-
getAllUserAttributeNames(): string
|
|
3769
|
+
getAllUserAttributeNames(): Set<string> {
|
|
3614
3770
|
return this.record.getUserAttributeNames();
|
|
3615
3771
|
}
|
|
3616
3772
|
|
|
@@ -3743,6 +3899,10 @@ export function findIdAttribute(inst: Instance): AttributeEntry | undefined {
|
|
|
3743
3899
|
return undefined;
|
|
3744
3900
|
}
|
|
3745
3901
|
|
|
3902
|
+
function defaultValueIsFunctionCall(dv: string): boolean {
|
|
3903
|
+
return dv.endsWith('()');
|
|
3904
|
+
}
|
|
3905
|
+
|
|
3746
3906
|
function maybeSetDefaultAttributeValues(
|
|
3747
3907
|
schema: RecordSchema,
|
|
3748
3908
|
attributes: InstanceAttributes
|
|
@@ -3752,10 +3912,12 @@ function maybeSetDefaultAttributeValues(
|
|
|
3752
3912
|
const cv = attributes.get(k);
|
|
3753
3913
|
if (cv === undefined || cv === null) {
|
|
3754
3914
|
if (isString(v)) {
|
|
3755
|
-
if (v
|
|
3756
|
-
|
|
3757
|
-
|
|
3758
|
-
|
|
3915
|
+
if (defaultValueIsFunctionCall(v)) {
|
|
3916
|
+
try {
|
|
3917
|
+
v = eval(v);
|
|
3918
|
+
} catch {
|
|
3919
|
+
v = (0, eval)(`globalThis.${v}`);
|
|
3920
|
+
}
|
|
3759
3921
|
}
|
|
3760
3922
|
}
|
|
3761
3923
|
attributes.set(k, v);
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
Decision,
|
|
21
21
|
fetchModule,
|
|
22
22
|
getDecision,
|
|
23
|
+
getGlobalRetry,
|
|
23
24
|
Instance,
|
|
24
25
|
instanceToObject,
|
|
25
26
|
isAgent,
|
|
@@ -198,11 +199,16 @@ export class AgentInstance {
|
|
|
198
199
|
if (agent.retry) {
|
|
199
200
|
let n = agent.retry;
|
|
200
201
|
if (!isFqName(n)) {
|
|
201
|
-
|
|
202
|
+
agent.retryObj = getGlobalRetry(n);
|
|
203
|
+
if (agent.retryObj === undefined) {
|
|
204
|
+
n = `${agent.moduleName}/${n}`;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
if (agent.retryObj === undefined) {
|
|
208
|
+
const parts = splitFqName(n);
|
|
209
|
+
const m = fetchModule(parts[0]);
|
|
210
|
+
agent.retryObj = m.getRetry(parts[1]);
|
|
202
211
|
}
|
|
203
|
-
const parts = splitFqName(n);
|
|
204
|
-
const m = fetchModule(parts[0]);
|
|
205
|
-
agent.retryObj = m.getRetry(parts[1]);
|
|
206
212
|
}
|
|
207
213
|
return agent;
|
|
208
214
|
}
|
|
@@ -36,6 +36,7 @@ entity User {
|
|
|
36
36
|
email Email @unique @indexed,
|
|
37
37
|
firstName String,
|
|
38
38
|
lastName String,
|
|
39
|
+
profilePicture String @optional,
|
|
39
40
|
lastLoginTime DateTime @default(now()),
|
|
40
41
|
status @enum("Active", "Invited", "Inactive") @default("Active"),
|
|
41
42
|
@rbac [(allow: [read, delete, update, create], where: auth.user = this.id)],
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
isString,
|
|
9
9
|
restoreSpecialChars,
|
|
10
10
|
makeCoreModuleName,
|
|
11
|
+
nameToPath,
|
|
11
12
|
} from '../util.js';
|
|
12
13
|
import {
|
|
13
14
|
fetchModule,
|
|
@@ -27,7 +28,7 @@ import {
|
|
|
27
28
|
} from '../interpreter.js';
|
|
28
29
|
import { logger } from '../logger.js';
|
|
29
30
|
import { Statement } from '../../language/generated/ast.js';
|
|
30
|
-
import { parseModule, parseStatements } from '../../language/parser.js';
|
|
31
|
+
import { objectToQueryPattern, parseModule, parseStatements } from '../../language/parser.js';
|
|
31
32
|
import { GenericResolver, Resolver } from '../resolvers/interface.js';
|
|
32
33
|
import {
|
|
33
34
|
FlowSuspensionTag,
|
|
@@ -48,7 +49,8 @@ entity timer {
|
|
|
48
49
|
duration Int,
|
|
49
50
|
unit @enum("millisecond", "second", "minute", "hour") @default("second"),
|
|
50
51
|
trigger String,
|
|
51
|
-
|
|
52
|
+
repeat Boolean @default(true),
|
|
53
|
+
status @enum("I", "C", "R") @default("I") @indexed // Inited, Cancelled, Running
|
|
52
54
|
}
|
|
53
55
|
|
|
54
56
|
entity auditlog {
|
|
@@ -56,7 +58,7 @@ entity auditlog {
|
|
|
56
58
|
action @enum("c", "d", "u"), // Create, Delete, Update
|
|
57
59
|
resource String, // __path__
|
|
58
60
|
timestamp DateTime @default(now()),
|
|
59
|
-
|
|
61
|
+
diff Any @optional,
|
|
60
62
|
user String,
|
|
61
63
|
token String @optional
|
|
62
64
|
}
|
|
@@ -161,6 +163,14 @@ entity Migration {
|
|
|
161
163
|
ups String @optional,
|
|
162
164
|
downs String @optional
|
|
163
165
|
}
|
|
166
|
+
|
|
167
|
+
@public event Query {
|
|
168
|
+
q Any
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
workflow Query {
|
|
172
|
+
await Core.doRawQuery(Query.q)
|
|
173
|
+
}
|
|
164
174
|
`;
|
|
165
175
|
|
|
166
176
|
export const CoreModules: string[] = [];
|
|
@@ -183,25 +193,94 @@ export function registerCoreModules() {
|
|
|
183
193
|
});
|
|
184
194
|
}
|
|
185
195
|
|
|
186
|
-
|
|
187
|
-
|
|
196
|
+
function isTimerCancelled(inst: Instance): boolean {
|
|
197
|
+
return inst.lookup('status') === 'C';
|
|
188
198
|
}
|
|
189
199
|
|
|
190
|
-
|
|
200
|
+
// If the timer is deleted or its status is set to 'C' (cancelled), then clear the associated timer.
|
|
201
|
+
async function maybeClearTimer(name: string, timer: NodeJS.Timeout, env: Environment) {
|
|
191
202
|
await parseAndEvaluateStatement(`{agentlang/timer {name? "${name}"}}`, undefined, env).then(
|
|
192
203
|
(result: any) => {
|
|
193
|
-
if (
|
|
204
|
+
if (
|
|
205
|
+
result === null ||
|
|
206
|
+
(result instanceof Array && (result.length == 0 || isTimerCancelled(result[0])))
|
|
207
|
+
) {
|
|
194
208
|
clearInterval(timer);
|
|
195
209
|
}
|
|
196
210
|
}
|
|
197
211
|
);
|
|
198
212
|
}
|
|
199
213
|
|
|
214
|
+
export function triggerTimer(timerInst: Instance): Instance {
|
|
215
|
+
const dur = timerInst.lookup('duration');
|
|
216
|
+
const unit = timerInst.lookup('unit');
|
|
217
|
+
let millisecs = 0;
|
|
218
|
+
switch (unit) {
|
|
219
|
+
case 'millisecond': {
|
|
220
|
+
millisecs = dur;
|
|
221
|
+
break;
|
|
222
|
+
}
|
|
223
|
+
case 'second': {
|
|
224
|
+
millisecs = dur * 1000;
|
|
225
|
+
break;
|
|
226
|
+
}
|
|
227
|
+
case 'minute': {
|
|
228
|
+
millisecs = dur * 60 * 1000;
|
|
229
|
+
break;
|
|
230
|
+
}
|
|
231
|
+
case 'hour': {
|
|
232
|
+
millisecs = dur * 60 * 60 * 1000;
|
|
233
|
+
break;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
const eventName = nameToPath(timerInst.lookup('trigger'));
|
|
237
|
+
const m = eventName.hasModule() ? eventName.getModuleName() : timerInst.moduleName;
|
|
238
|
+
const n = eventName.getEntryName();
|
|
239
|
+
const inst = makeInstance(m, n, newInstanceAttributes());
|
|
240
|
+
const name = timerInst.lookup('name');
|
|
241
|
+
const repeat = timerInst.lookup('repeat');
|
|
242
|
+
const timer = setInterval(async () => {
|
|
243
|
+
const env = new Environment();
|
|
244
|
+
try {
|
|
245
|
+
await evaluate(
|
|
246
|
+
inst,
|
|
247
|
+
(result: any) => logger.debug(`Timer ${name} ran with result ${result}`),
|
|
248
|
+
env
|
|
249
|
+
);
|
|
250
|
+
await env.commitAllTransactions();
|
|
251
|
+
if (!repeat) clearInterval(timer);
|
|
252
|
+
else await maybeClearTimer(name, timer, env);
|
|
253
|
+
} catch (reason: any) {
|
|
254
|
+
logger.error(`Timer ${name} raised error: ${reason}`);
|
|
255
|
+
}
|
|
256
|
+
}, millisecs);
|
|
257
|
+
timerInst.attributes.set('status', 'R');
|
|
258
|
+
return timerInst;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
export async function saveTimerStatus(timerInst: Instance): Promise<boolean> {
|
|
262
|
+
const name = timerInst.lookup('name');
|
|
263
|
+
const status = timerInst.lookup('status');
|
|
264
|
+
const env = new Environment();
|
|
265
|
+
try {
|
|
266
|
+
await parseAndEvaluateStatement(`{agentlang/timer {name? "${name}", "status": "${status}"}}`);
|
|
267
|
+
await env.commitAllTransactions();
|
|
268
|
+
} catch (reason: any) {
|
|
269
|
+
logger.warn(`Failed to save status of timer ${name} - ${reason}`);
|
|
270
|
+
return false;
|
|
271
|
+
}
|
|
272
|
+
return true;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
export async function lookupTimersWithRunningStatus(): Promise<Instance[]> {
|
|
276
|
+
return await parseAndEvaluateStatement(`{agentlang/timer {status? "R"}}`);
|
|
277
|
+
}
|
|
278
|
+
|
|
200
279
|
async function addAudit(
|
|
201
280
|
env: Environment,
|
|
202
281
|
action: 'c' | 'd' | 'u',
|
|
203
282
|
resource: string,
|
|
204
|
-
|
|
283
|
+
diff?: object
|
|
205
284
|
) {
|
|
206
285
|
const user = env.getActiveUser();
|
|
207
286
|
const token = env.getActiveToken();
|
|
@@ -211,7 +290,7 @@ async function addAudit(
|
|
|
211
290
|
`{agentlang/auditlog {
|
|
212
291
|
action "${action}",
|
|
213
292
|
resource "${resource}",
|
|
214
|
-
|
|
293
|
+
diff "${diff ? escapeSpecialChars(JSON.stringify(diff)) : ''}",
|
|
215
294
|
user "${user}",
|
|
216
295
|
token "${token ? token : ''}"
|
|
217
296
|
}}`,
|
|
@@ -225,24 +304,16 @@ async function addAudit(
|
|
|
225
304
|
}
|
|
226
305
|
}
|
|
227
306
|
|
|
228
|
-
export async function addCreateAudit(resource: string, env: Environment) {
|
|
229
|
-
await addAudit(env, 'c', resource);
|
|
307
|
+
export async function addCreateAudit(resource: string, env: Environment, init: object) {
|
|
308
|
+
await addAudit(env, 'c', resource, init);
|
|
230
309
|
}
|
|
231
310
|
|
|
232
|
-
export async function addDeleteAudit(
|
|
233
|
-
resource
|
|
234
|
-
previous_value: Instance | undefined,
|
|
235
|
-
env: Environment
|
|
236
|
-
) {
|
|
237
|
-
await addAudit(env, 'd', resource, previous_value);
|
|
311
|
+
export async function addDeleteAudit(resource: string, diff: object | undefined, env: Environment) {
|
|
312
|
+
await addAudit(env, 'd', resource, diff);
|
|
238
313
|
}
|
|
239
314
|
|
|
240
|
-
export async function addUpdateAudit(
|
|
241
|
-
resource
|
|
242
|
-
previous_value: Instance | undefined,
|
|
243
|
-
env: Environment
|
|
244
|
-
) {
|
|
245
|
-
await addAudit(env, 'u', resource, previous_value);
|
|
315
|
+
export async function addUpdateAudit(resource: string, diff: object | undefined, env: Environment) {
|
|
316
|
+
await addAudit(env, 'u', resource, diff);
|
|
246
317
|
}
|
|
247
318
|
|
|
248
319
|
export async function createSuspension(
|
|
@@ -664,3 +735,8 @@ export function migrationDowns(inst: Instance): string[] | undefined {
|
|
|
664
735
|
}
|
|
665
736
|
return undefined;
|
|
666
737
|
}
|
|
738
|
+
|
|
739
|
+
export async function doRawQuery(q: any): Promise<any> {
|
|
740
|
+
const qs = objectToQueryPattern(q);
|
|
741
|
+
return await parseAndEvaluateStatement(qs);
|
|
742
|
+
}
|
package/src/runtime/monitor.ts
CHANGED
|
@@ -33,6 +33,12 @@ export function getSubscriptionEvent(resolverName: string): string | undefined {
|
|
|
33
33
|
return subscriptionEvents.get(resolverName);
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
export type WhereClause = {
|
|
37
|
+
attrName: string;
|
|
38
|
+
op: string;
|
|
39
|
+
qval: any;
|
|
40
|
+
};
|
|
41
|
+
|
|
36
42
|
export class Resolver {
|
|
37
43
|
protected authInfo: ResolverAuthInfo = DefaultAuthInfo;
|
|
38
44
|
protected env: Environment | undefined;
|
|
@@ -131,10 +137,11 @@ export class Resolver {
|
|
|
131
137
|
joinInfo: JoinInfo[],
|
|
132
138
|
intoSpec: Map<string, string>,
|
|
133
139
|
distinct: boolean = false,
|
|
134
|
-
rawJoinSpec?: JoinSpec
|
|
140
|
+
rawJoinSpec?: JoinSpec[],
|
|
141
|
+
whereClauses?: WhereClause[]
|
|
135
142
|
): Promise<any> {
|
|
136
143
|
return this.notImpl(
|
|
137
|
-
`queryByJoin(${inst}, ${joinInfo}, ${intoSpec}, ${distinct} ${rawJoinSpec})`
|
|
144
|
+
`queryByJoin(${inst}, ${joinInfo}, ${intoSpec}, ${distinct}, ${rawJoinSpec}, ${whereClauses})`
|
|
138
145
|
);
|
|
139
146
|
}
|
|
140
147
|
|