agentlang
Version:
The easiest way to build the most reliable AI agents - enterprise-grade teams of AI agents that collaborate with each other and humans
389 lines (321 loc) • 9.58 kB
text/typescript
import { Expr, Pattern, Statement } from '../language/generated/ast.js';
export const PathAttributeName: string = '__path__';
export const PathAttributeNameQuery: string = '__path__?';
export const ParentAttributeName: string = '__parent__';
export const DeletedFlagAttributeName: string = '__is_deleted__';
export function isPathAttribute(n: string): boolean {
return n.startsWith(PathAttributeName);
}
export type UnautInfo = {
opr: string;
entity: string;
};
function asUnauthMessage(obj: string | UnautInfo): string {
if (typeof obj == 'string') {
return obj;
} else {
return `User not authorised to perform '${obj.opr}' on ${obj.entity}`;
}
}
export class UnauthorisedError extends Error {
constructor(message?: string | UnautInfo, options?: ErrorOptions) {
super(
message ? asUnauthMessage(message) : 'User not authorised to perform this operation',
options
);
}
}
export class BadRequestError extends Error {
constructor(message?: string, options?: ErrorOptions) {
super(message ? asUnauthMessage(message) : 'BadRequest', options);
}
}
export class UserNotFoundError extends Error {
constructor(message?: string, options?: ErrorOptions) {
super(message || 'User not found', options);
}
}
export class UserNotConfirmedError extends Error {
constructor(message?: string, options?: ErrorOptions) {
super(
message || 'User account is not confirmed. Please check your email for verification code.',
options
);
}
}
export class PasswordResetRequiredError extends Error {
constructor(message?: string, options?: ErrorOptions) {
super(message || 'Password reset is required for this account', options);
}
}
export class TooManyRequestsError extends Error {
constructor(message?: string, options?: ErrorOptions) {
super(message || 'Too many requests. Please try again later.', options);
}
}
export class InvalidParameterError extends Error {
constructor(message?: string, options?: ErrorOptions) {
super(message || 'Invalid parameters provided', options);
}
}
export class ExpiredCodeError extends Error {
constructor(message?: string, options?: ErrorOptions) {
super(message || 'The verification code has expired. Please request a new one.', options);
}
}
export class CodeMismatchError extends Error {
constructor(message?: string, options?: ErrorOptions) {
super(message || 'The verification code is incorrect. Please try again.', options);
}
}
export let FetchModuleFn: any = undefined;
export function setModuleFnFetcher(f: Function) {
FetchModuleFn = f;
}
export let SetSubscription: any = undefined;
export function setSubscriptionFn(f: Function) {
SetSubscription = f;
}
export const ForceReadPermFlag = 'f-r-f';
export const FlowSuspensionTag = `--`;
export enum SubGraphType {
EVENT,
IF,
FOR_EACH,
DELETE,
PURGE,
RETURN,
AGENT,
NONE,
}
export class ExecGraphNode {
code: Statement | Pattern | Expr;
codeStr: string | undefined;
subGraphIndex: number;
subGraphType: SubGraphType;
constructor(
statement: Statement | Pattern | Expr,
subGraphIndex: number = -1,
subGraphType: SubGraphType = SubGraphType.NONE
) {
this.code = statement;
this.codeStr = this.code.$cstNode?.text;
this.subGraphType = subGraphType;
this.subGraphIndex = subGraphIndex;
}
asObject(): any {
const r: any = { code: this.codeStr };
if (this.subGraphType != SubGraphType.NONE) {
r.type = SubGraphType[this.subGraphType];
}
return r;
}
}
export class ExecGraph {
private rootNodes: ExecGraphNode[];
private subGraphs: ExecGraph[];
private parentGraph: ExecGraph | undefined = undefined;
private eventName: string | undefined;
private activeModuleName: string | undefined;
private hasAgentsFlag: boolean = false;
private loopBody: boolean = false;
static Empty = new ExecGraph();
static isEmpty(g: ExecGraph): boolean {
return Object.is(ExecGraph.Empty, g);
}
constructor() {
this.rootNodes = new Array<ExecGraphNode>();
this.subGraphs = new Array<ExecGraph>();
}
pushNode(node: ExecGraphNode): ExecGraph {
this.rootNodes.push(node);
return this;
}
pushSubGraph(execGraph: ExecGraph): ExecGraph {
execGraph.parentGraph = this;
this.subGraphs.push(execGraph);
return this;
}
getSubGraphsLength(): number {
return this.subGraphs.length;
}
getLastSubGraphIndex(): number {
return this.subGraphs.length - 1;
}
fetchSubGraphAt(index: number): ExecGraph {
if (index < 0 || index >= this.subGraphs.length) {
throw new Error(`Invalid sub-graph index: ${index}`);
}
return this.subGraphs[index];
}
fetchForEachBodySubGraph(): ExecGraph {
return this.fetchSubGraphAt(this.subGraphs.length - 1);
}
fetchIfConsequentSubGraph(): ExecGraph {
if (this.subGraphs.length >= 2) {
return this.fetchSubGraphAt(this.subGraphs.length - 2);
} else {
return this.fetchSubGraphAt(this.subGraphs.length - 1);
}
}
fetchIfAlternativeSubGraph(): ExecGraph | undefined {
if (this.subGraphs.length >= 2) {
return this.fetchSubGraphAt(this.subGraphs.length - 1);
} else {
return undefined;
}
}
getRootNodes(): ExecGraphNode[] {
return this.rootNodes;
}
setActiveModuleName(moduleName: string | undefined): ExecGraph {
if (moduleName) this.activeModuleName = moduleName;
return this;
}
getActiveModuleName(): string | undefined {
return this.activeModuleName;
}
getParentGraph(): ExecGraph | undefined {
return this.parentGraph;
}
setEventName(eventName: string | undefined): ExecGraph {
if (eventName !== undefined) {
this.eventName = eventName;
}
return this;
}
getEventName(): string | undefined {
return this.eventName;
}
setHasAgents(flag: boolean): ExecGraph {
this.hasAgentsFlag = flag;
if (this.parentGraph) {
this.parentGraph.setHasAgents(flag);
}
return this;
}
hasAgents(): boolean {
return this.hasAgentsFlag;
}
canCache(): boolean {
return !this.hasAgentsFlag;
}
setIsLoopBody(): ExecGraph {
this.loopBody = true;
return this;
}
isLoopBody(): boolean {
return this.loopBody;
}
asObject(): any[] {
const nodeObjs = new Array<any>();
this.rootNodes.forEach((node: ExecGraphNode) => {
const n = node.asObject();
if (node.subGraphIndex >= 0) {
const g = this.subGraphs[node.subGraphIndex];
const gobj = g.asObject();
if (node.subGraphType == SubGraphType.FOR_EACH) {
const stmt = node.code as Statement;
n.var = stmt.pattern.forEach?.var;
n.source = gobj;
n.body = g.fetchForEachBodySubGraph().asObject();
} else if (node.subGraphType == SubGraphType.IF) {
n.condition = gobj;
n.body = g.fetchIfConsequentSubGraph().asObject();
const a = g.fetchIfAlternativeSubGraph();
if (a) {
n.else = a.asObject();
}
} else {
n.subGraph = gobj;
}
}
nodeObjs.push(n);
});
return nodeObjs;
}
}
export class ExecGraphWalker {
private offset = 0;
private maxOffset: number;
private rootNodes;
constructor(execGraph: ExecGraph) {
this.rootNodes = execGraph.getRootNodes();
this.maxOffset = this.rootNodes.length;
}
hasNext(): boolean {
return this.offset < this.maxOffset;
}
nextNode(): ExecGraphNode {
if (this.offset < this.maxOffset) {
return this.rootNodes[this.offset++];
}
throw new Error('End of execution-graph');
}
currentNode(): ExecGraphNode {
if (this.offset > 0) {
return this.rootNodes[this.offset - 1];
} else {
return this.rootNodes[0];
}
}
reset(): ExecGraphWalker {
this.offset = 0;
return this;
}
}
export type FkSpec = {
moduleName: string;
entityName: string;
columnName: string;
targetModuleName: string;
targetEntityName: string;
targetColumnName: string;
onDelete: 'CASCADE' | 'SET NULL' | 'SET DEFAULT' | undefined;
onUpdate: 'CASCADE' | 'SET NULL' | 'SET DEFAULT' | undefined;
};
enum RuntimeModeTag {
DEV,
PROD,
INIT_SCHEMA,
RUN_MIGRATION,
UNDO_MIGRATION,
GENERATE_MIGRATION,
}
let RuntimeMode: RuntimeModeTag = RuntimeModeTag.DEV;
export function setRuntimeMode_dev() {
RuntimeMode = RuntimeModeTag.DEV;
}
export function setRuntimeMode_prod() {
RuntimeMode = RuntimeModeTag.PROD;
}
export function setRuntimeMode_init_schema() {
RuntimeMode = RuntimeModeTag.INIT_SCHEMA;
}
export function setRuntimeMode_migration() {
RuntimeMode = RuntimeModeTag.RUN_MIGRATION;
}
export function setRuntimeMode_undo_migration() {
RuntimeMode = RuntimeModeTag.UNDO_MIGRATION;
}
export function setRuntimeMode_generate_migration() {
RuntimeMode = RuntimeModeTag.GENERATE_MIGRATION;
}
export function isRuntimeMode_dev(): boolean {
return RuntimeMode === RuntimeModeTag.DEV;
}
export function isRuntimeMode_prod(): boolean {
return RuntimeMode === RuntimeModeTag.PROD;
}
export function isRuntimeMode_init_schema(): boolean {
return RuntimeMode === RuntimeModeTag.INIT_SCHEMA;
}
export function isRuntimeMode_migration(): boolean {
return RuntimeMode === RuntimeModeTag.RUN_MIGRATION;
}
export function isRuntimeMode_generate_migration(): boolean {
return RuntimeMode === RuntimeModeTag.GENERATE_MIGRATION;
}
export function isRuntimeMode_undo_migration(): boolean {
return RuntimeMode === RuntimeModeTag.UNDO_MIGRATION;
}