agentlang 0.7.8 → 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.
Files changed (129) hide show
  1. package/out/api/http.d.ts.map +1 -1
  2. package/out/api/http.js +8 -1
  3. package/out/api/http.js.map +1 -1
  4. package/out/cli/main.d.ts.map +1 -1
  5. package/out/cli/main.js +33 -2
  6. package/out/cli/main.js.map +1 -1
  7. package/out/extension/main.cjs +250 -250
  8. package/out/extension/main.cjs.map +2 -2
  9. package/out/language/agentlang-validator.d.ts +1 -2
  10. package/out/language/agentlang-validator.d.ts.map +1 -1
  11. package/out/language/agentlang-validator.js +0 -39
  12. package/out/language/agentlang-validator.js.map +1 -1
  13. package/out/language/generated/ast.d.ts +62 -11
  14. package/out/language/generated/ast.d.ts.map +1 -1
  15. package/out/language/generated/ast.js +75 -3
  16. package/out/language/generated/ast.js.map +1 -1
  17. package/out/language/generated/grammar.d.ts.map +1 -1
  18. package/out/language/generated/grammar.js +758 -239
  19. package/out/language/generated/grammar.js.map +1 -1
  20. package/out/language/main.cjs +1370 -824
  21. package/out/language/main.cjs.map +4 -4
  22. package/out/language/parser.d.ts +1 -0
  23. package/out/language/parser.d.ts.map +1 -1
  24. package/out/language/parser.js +44 -7
  25. package/out/language/parser.js.map +1 -1
  26. package/out/language/syntax.d.ts +1 -1
  27. package/out/language/syntax.d.ts.map +1 -1
  28. package/out/language/syntax.js +22 -13
  29. package/out/language/syntax.js.map +1 -1
  30. package/out/runtime/api.d.ts +4 -0
  31. package/out/runtime/api.d.ts.map +1 -1
  32. package/out/runtime/api.js +9 -0
  33. package/out/runtime/api.js.map +1 -1
  34. package/out/runtime/auth/cognito.d.ts.map +1 -1
  35. package/out/runtime/auth/cognito.js +4 -4
  36. package/out/runtime/auth/cognito.js.map +1 -1
  37. package/out/runtime/auth/defs.d.ts +9 -1
  38. package/out/runtime/auth/defs.d.ts.map +1 -1
  39. package/out/runtime/auth/defs.js +23 -2
  40. package/out/runtime/auth/defs.js.map +1 -1
  41. package/out/runtime/defs.d.ts +5 -0
  42. package/out/runtime/defs.d.ts.map +1 -1
  43. package/out/runtime/defs.js +16 -0
  44. package/out/runtime/defs.js.map +1 -1
  45. package/out/runtime/exec-graph.js +1 -1
  46. package/out/runtime/exec-graph.js.map +1 -1
  47. package/out/runtime/interpreter.d.ts +6 -1
  48. package/out/runtime/interpreter.d.ts.map +1 -1
  49. package/out/runtime/interpreter.js +144 -112
  50. package/out/runtime/interpreter.js.map +1 -1
  51. package/out/runtime/loader.d.ts +1 -1
  52. package/out/runtime/loader.d.ts.map +1 -1
  53. package/out/runtime/loader.js +74 -27
  54. package/out/runtime/loader.js.map +1 -1
  55. package/out/runtime/module.d.ts +41 -11
  56. package/out/runtime/module.d.ts.map +1 -1
  57. package/out/runtime/module.js +238 -50
  58. package/out/runtime/module.js.map +1 -1
  59. package/out/runtime/modules/ai.d.ts.map +1 -1
  60. package/out/runtime/modules/ai.js +13 -6
  61. package/out/runtime/modules/ai.js.map +1 -1
  62. package/out/runtime/modules/auth.d.ts +2 -1
  63. package/out/runtime/modules/auth.d.ts.map +1 -1
  64. package/out/runtime/modules/auth.js +93 -3
  65. package/out/runtime/modules/auth.js.map +1 -1
  66. package/out/runtime/modules/core.d.ts +7 -5
  67. package/out/runtime/modules/core.d.ts.map +1 -1
  68. package/out/runtime/modules/core.js +93 -16
  69. package/out/runtime/modules/core.js.map +1 -1
  70. package/out/runtime/monitor.d.ts.map +1 -1
  71. package/out/runtime/monitor.js +1 -0
  72. package/out/runtime/monitor.js.map +1 -1
  73. package/out/runtime/resolvers/interface.d.ts +6 -1
  74. package/out/runtime/resolvers/interface.d.ts.map +1 -1
  75. package/out/runtime/resolvers/interface.js +2 -2
  76. package/out/runtime/resolvers/interface.js.map +1 -1
  77. package/out/runtime/resolvers/sqldb/database.d.ts +19 -2
  78. package/out/runtime/resolvers/sqldb/database.d.ts.map +1 -1
  79. package/out/runtime/resolvers/sqldb/database.js +107 -21
  80. package/out/runtime/resolvers/sqldb/database.js.map +1 -1
  81. package/out/runtime/resolvers/sqldb/dbutil.d.ts +1 -0
  82. package/out/runtime/resolvers/sqldb/dbutil.d.ts.map +1 -1
  83. package/out/runtime/resolvers/sqldb/dbutil.js +25 -3
  84. package/out/runtime/resolvers/sqldb/dbutil.js.map +1 -1
  85. package/out/runtime/resolvers/sqldb/impl.d.ts +3 -2
  86. package/out/runtime/resolvers/sqldb/impl.d.ts.map +1 -1
  87. package/out/runtime/resolvers/sqldb/impl.js +80 -6
  88. package/out/runtime/resolvers/sqldb/impl.js.map +1 -1
  89. package/out/runtime/state.d.ts +58 -0
  90. package/out/runtime/state.d.ts.map +1 -1
  91. package/out/runtime/state.js +12 -0
  92. package/out/runtime/state.js.map +1 -1
  93. package/out/runtime/util.d.ts +1 -1
  94. package/out/runtime/util.d.ts.map +1 -1
  95. package/out/runtime/util.js +27 -13
  96. package/out/runtime/util.js.map +1 -1
  97. package/out/syntaxes/agentlang.monarch.js +1 -1
  98. package/out/syntaxes/agentlang.monarch.js.map +1 -1
  99. package/out/utils/fs-utils.d.ts +10 -0
  100. package/out/utils/fs-utils.d.ts.map +1 -1
  101. package/out/utils/fs-utils.js +14 -0
  102. package/out/utils/fs-utils.js.map +1 -1
  103. package/package.json +2 -1
  104. package/src/api/http.ts +8 -0
  105. package/src/cli/main.ts +38 -2
  106. package/src/language/agentlang-validator.ts +1 -51
  107. package/src/language/agentlang.langium +17 -4
  108. package/src/language/generated/ast.ts +147 -13
  109. package/src/language/generated/grammar.ts +758 -239
  110. package/src/language/parser.ts +43 -8
  111. package/src/language/syntax.ts +25 -12
  112. package/src/runtime/api.ts +16 -0
  113. package/src/runtime/auth/defs.ts +25 -2
  114. package/src/runtime/defs.ts +8 -0
  115. package/src/runtime/interpreter.ts +104 -76
  116. package/src/runtime/loader.ts +75 -25
  117. package/src/runtime/module.ts +194 -32
  118. package/src/runtime/modules/ai.ts +10 -4
  119. package/src/runtime/modules/auth.ts +1 -0
  120. package/src/runtime/modules/core.ts +99 -23
  121. package/src/runtime/monitor.ts +1 -0
  122. package/src/runtime/resolvers/interface.ts +9 -2
  123. package/src/runtime/resolvers/sqldb/database.ts +68 -17
  124. package/src/runtime/resolvers/sqldb/dbutil.ts +28 -6
  125. package/src/runtime/resolvers/sqldb/impl.ts +86 -14
  126. package/src/runtime/state.ts +14 -0
  127. package/src/runtime/util.ts +25 -12
  128. package/src/syntaxes/agentlang.monarch.ts +1 -1
  129. package/src/utils/fs-utils.ts +16 -0
@@ -69,6 +69,7 @@ import {
69
69
  addAgent,
70
70
  fetchModule,
71
71
  Retry,
72
+ addGlobalRetry,
72
73
  } from './module.js';
73
74
  import {
74
75
  asStringLiteralsMap,
@@ -81,6 +82,7 @@ import {
81
82
  preprocessRawConfig,
82
83
  registerInitFunction,
83
84
  rootRef,
85
+ ScratchModuleName,
84
86
  } from './util.js';
85
87
  import { getFileSystem, toFsPath, readFile, readdir, exists } from '../utils/fs-utils.js';
86
88
  import { URI } from 'vscode-uri';
@@ -348,10 +350,14 @@ async function evaluateConfigPatterns(cfgPats: string): Promise<any> {
348
350
  const wf = await parseWorkflow(cfgWf);
349
351
  const cfgStmts = new Array<Statement>();
350
352
  const initInsts = new Array<Statement>();
353
+ const deleted = new Set<string>();
351
354
  for (let i = 0; i < wf.statements.length; ++i) {
352
355
  const stmt: Statement = wf.statements[i];
353
356
  if (stmt.pattern.crudMap) {
354
- initInsts.push(await makeDeleteAllConfigStatement(stmt.pattern.crudMap));
357
+ if (!deleted.has(stmt.pattern.crudMap?.name)) {
358
+ initInsts.push(await makeDeleteAllConfigStatement(stmt.pattern.crudMap));
359
+ deleted.add(stmt.pattern.crudMap.name);
360
+ }
355
361
  initInsts.push(stmt);
356
362
  } else {
357
363
  cfgStmts.push(stmt);
@@ -377,20 +383,37 @@ async function evaluateConfigPatterns(cfgPats: string): Promise<any> {
377
383
  return undefined;
378
384
  }
379
385
 
380
- export async function loadAppConfig(configDir: string): Promise<Config> {
386
+ function isStringContent(content: string): boolean {
387
+ return content.includes('{');
388
+ }
389
+
390
+ export async function loadAppConfig(configDirOrContent: string): Promise<Config> {
391
+ const stringContent = isStringContent(configDirOrContent);
392
+
381
393
  let cfgObj: any = undefined;
382
- const fs = await getFileSystem();
383
- const alCfgFile = `${configDir}${path.sep}config.al`;
384
- if (await fs.exists(alCfgFile)) {
385
- const cfgPats = await fs.readFile(alCfgFile);
386
- if (canParse(cfgPats)) {
387
- cfgObj = await evaluateConfigPatterns(cfgPats);
394
+
395
+ if (!stringContent) {
396
+ const fs = await getFileSystem();
397
+ const alCfgFile = `${configDirOrContent}${path.sep}config.al`;
398
+ if (await fs.exists(alCfgFile)) {
399
+ configDirOrContent = await fs.readFile(alCfgFile);
388
400
  }
389
401
  }
402
+
403
+ if (canParse(configDirOrContent)) {
404
+ cfgObj = await evaluateConfigPatterns(configDirOrContent);
405
+ }
406
+
390
407
  try {
391
- const cfg = cfgObj
408
+ let cfg = cfgObj
392
409
  ? await configFromObject(cfgObj)
393
- : await loadRawConfig(`${configDir}${path.sep}app.config.json`);
410
+ : await loadRawConfig(`${configDirOrContent}${path.sep}app.config.json`);
411
+
412
+ const envAppConfig = typeof process !== 'undefined' ? process.env.APP_CONFIG : undefined;
413
+ if (envAppConfig) {
414
+ const envConfig = JSON.parse(envAppConfig);
415
+ cfg = { ...cfg, ...envConfig };
416
+ }
394
417
  return setAppConfig(cfg);
395
418
  } catch (err: any) {
396
419
  if (err instanceof z.ZodError) {
@@ -891,7 +914,7 @@ function addFlowDefinition(def: FlowDefinition, moduleName: string) {
891
914
  f = sdef;
892
915
  }
893
916
  }
894
- m.addFlow(def.name, f);
917
+ m.addFlow(def.name, def);
895
918
  registerFlow(`${moduleName}/${def.name}`, f);
896
919
  }
897
920
 
@@ -1161,6 +1184,7 @@ export async function internModule(
1161
1184
  // Process imports sequentially to ensure all JS modules are loaded before definitions
1162
1185
  for (const imp of module.imports as Import[]) {
1163
1186
  await importModule(imp.path, imp.name, moduleFileName);
1187
+ r.addImport({ name: imp.name, path: imp.path });
1164
1188
  }
1165
1189
  for (let i = 0; i < module.defs.length; ++i) {
1166
1190
  const def = module.defs[i];
@@ -1186,31 +1210,57 @@ export async function loadRawConfig(
1186
1210
  }
1187
1211
  }
1188
1212
 
1189
- function filterConfigEntityInstances(rawConfig: any): [any, Map<string, any>] {
1190
- const cfg = new Map<string, any>();
1191
- const insts = new Map<string, any>();
1192
- Object.entries(rawConfig).forEach(([key, value]: [string, any]) => {
1193
- if (isFqName(key)) {
1194
- insts.set(key, value);
1195
- } else {
1196
- cfg.set(key, value);
1197
- }
1213
+ function filterConfigEntityInstances(rawConfig: any): [any, Array<any>] {
1214
+ let cfg: any = undefined;
1215
+ const insts = new Array<any>();
1216
+ const oldFormat = Object.keys(rawConfig).some((k: string) => {
1217
+ return k === 'store' || k === 'service';
1198
1218
  });
1199
- return [Object.fromEntries(cfg), insts];
1219
+ const newFormat = !oldFormat;
1220
+ if (newFormat) {
1221
+ Object.entries(rawConfig).forEach(([key, value]: [string, any]) => {
1222
+ if (key === 'agentlang') {
1223
+ cfg = value;
1224
+ } else {
1225
+ if (value instanceof Array) {
1226
+ value.forEach((v: any) => {
1227
+ insts.push(v);
1228
+ });
1229
+ } else {
1230
+ insts.push(value);
1231
+ }
1232
+ }
1233
+ });
1234
+ if (cfg === undefined) cfg = {};
1235
+ return [cfg, insts];
1236
+ } else {
1237
+ return [rawConfig, insts];
1238
+ }
1200
1239
  }
1201
1240
 
1202
1241
  async function configFromObject(cfgObj: any, validate: boolean = true): Promise<any> {
1203
1242
  const rawConfig = preprocessRawConfig(cfgObj);
1204
- if (validate) {
1243
+ if (validate && rawConfig) {
1205
1244
  const [cfg, insts] = filterConfigEntityInstances(rawConfig);
1206
1245
  const pats = new Array<string>();
1207
- insts.forEach((v: any, k: string) => {
1208
- pats.push(`{${k} ${objectAsString(v)}}`);
1246
+ insts.forEach((v: any) => {
1247
+ const n = Object.keys(v)[0];
1248
+ const attrs = v[n];
1249
+ pats.push(`{${n} ${objectAsString(attrs)}}`);
1209
1250
  });
1210
1251
  if (pats.length > 0) {
1211
1252
  await evaluateConfigPatterns(pats.join('\n'));
1212
1253
  }
1213
- return ConfigSchema.parse(cfg);
1254
+ const result = ConfigSchema.parse(cfg);
1255
+ cfg.retry?.forEach((r: any) => {
1256
+ const retry: Retry = new Retry(r.name, ScratchModuleName, r.attempts)
1257
+ .setBackoffDelay(r.backoff.delay)
1258
+ .setBackoffFactor(r.backoff.factor)
1259
+ .setBackoffStrategy(r.backoff.strategy[0])
1260
+ .setBackoffMagnitude(r.backoff.magnitude);
1261
+ addGlobalRetry(retry);
1262
+ });
1263
+ return result;
1214
1264
  }
1215
1265
  return rawConfig;
1216
1266
  }
@@ -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) && propValue != 'now()' && propValue != 'uuid()') {
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
- const recSchema: RecordSchema = newRecordSchema();
646
- this.schema.forEach((attrSpec: AttributeSpec, n: string) => {
647
- if (!isSystemAttribute(attrSpec)) {
648
- recSchema.set(n, attrSpec);
649
- }
650
- });
651
- return recSchema;
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
- getUserAttributeNames(): string[] {
655
- return [...this.getUserAttributes().keys()];
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?: string) {
1648
+ constructor(name: string, moduleName: string, flow?: FlowDefinition) {
1599
1649
  super(name, moduleName);
1600
- this.flowSteps = new Array<string>();
1601
- flow?.split('\n').forEach((step: string) => {
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.forEach((s: string) => {
1635
- const fp = FlowStepPattern.Parse(s);
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, flowString?: string): Flow {
2035
- const flow: Flow = new Flow(Flow.asFlowName(name), this.name, flowString);
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 == 'uuid()') {
3756
- v = crypto.randomUUID();
3757
- } else if (v == 'now()') {
3758
- v = now();
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
- n = `${agent.moduleName}/${n}`;
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)],