UNPKG

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

688 lines 19.7 kB
var _a; import { parseHelper } from 'langium/test'; import { escapeQueryName, trimQuotes } from '../runtime/util.js'; import { isDecisionDefinition } from './generated/ast.js'; import { createAgentlangServices } from './agentlang-module.js'; import { EmptyFileSystem } from 'langium'; import { introspect, parseModule } from './parser.js'; export class BasePattern { setAlias(alias) { this.alias = alias; return this; } unsetAlias() { this.alias = undefined; return this; } addAlias(alias) { if (this.aliases === undefined) { this.aliases = []; } this.aliases.push(alias); } setAliases(aliases) { this.aliases = aliases; } addHandler(k, handler) { if (this.handlers === undefined) { this.handlers = new Map(); } this.handlers.set(k, handler); } aliasesAsString() { if (this.alias) { return ` @as ${this.alias}`; } else if (this.aliases) { return ` @as [${this.aliases.join(',')}]`; } else { return undefined; } } handlersAsString() { if (this.handlers) { let s = '{'; this.handlers.forEach((handler, k) => { s = `${s} ${k} ${handler.toString()}\n`; }); return s + '}'; } else { return undefined; } } hintsAsString() { const a = this.aliasesAsString(); const h = this.handlersAsString(); if (!a && !h) return ''; if (a && !h) return a; if (!a && h) return h; return `${a}\n${h}`; } toString() { return ''; } } export const EmptyBasePattern = new BasePattern(); export var LiteralPatternType; (function (LiteralPatternType) { LiteralPatternType[LiteralPatternType["ID"] = 0] = "ID"; LiteralPatternType[LiteralPatternType["NUMBER"] = 1] = "NUMBER"; LiteralPatternType[LiteralPatternType["BOOLEAN"] = 2] = "BOOLEAN"; LiteralPatternType[LiteralPatternType["STRING"] = 3] = "STRING"; LiteralPatternType[LiteralPatternType["REFERENCE"] = 4] = "REFERENCE"; LiteralPatternType[LiteralPatternType["MAP"] = 5] = "MAP"; LiteralPatternType[LiteralPatternType["ARRAY"] = 6] = "ARRAY"; })(LiteralPatternType || (LiteralPatternType = {})); export class LiteralPattern extends BasePattern { constructor(type, value) { super(); this.type = type; this.value = value; } static Id(value) { return new LiteralPattern(LiteralPatternType.ID, value); } static Number(value) { return new LiteralPattern(LiteralPatternType.NUMBER, value); } static Boolean(value) { return new LiteralPattern(LiteralPatternType.BOOLEAN, value); } static String(value) { return new LiteralPattern(LiteralPatternType.STRING, value); } static Reference(value) { if (value.indexOf('.') < 0) { throw new Error(`${value} does not look like a reference`); } return new LiteralPattern(LiteralPatternType.REFERENCE, value); } static Map(value) { return new LiteralPattern(LiteralPatternType.MAP, value); } static Array(value) { return new LiteralPattern(LiteralPatternType.ARRAY, value); } toString() { let s = ''; switch (this.type) { case LiteralPatternType.ARRAY: { const a = this.value; s = `[${a .map((v) => { return v.toString(); }) .join(', ')}]`; break; } case LiteralPatternType.MAP: { const m = this.value; const arr = new Array(); m.forEach((v, key) => { let k = key.str; if (k === undefined) { k = key.num; } else { k = `"${k}"`; } if (k === undefined) { k = key.bool; } arr.push(`${k}: ${v.toString()}`); }); s = `{${arr.join(', ')}}`; break; } case LiteralPatternType.STRING: { s = `"${this.value}"`; break; } default: s = this.value.toString(); } return s.concat(this.hintsAsString()); } } LiteralPattern.EmptyArray = new LiteralPattern(LiteralPatternType.ARRAY, []); export function isLiteralPattern(p) { return p instanceof LiteralPattern; } export function isReferenceLiteral(p) { return p.type == LiteralPatternType.REFERENCE; } export function referenceParts(p) { if (isReferenceLiteral(p)) { const s = p.value; return s.split('.'); } return undefined; } export function isStringLiteral(p) { return p.type == LiteralPatternType.STRING; } export function isNumberLiteral(p) { return p.type == LiteralPatternType.NUMBER; } export function isBooleanLiteral(p) { return p.type == LiteralPatternType.BOOLEAN; } export function isIdentifierLiteral(p) { return p.type == LiteralPatternType.ID; } export function isArrayLiteral(p) { return p.type == LiteralPatternType.ARRAY; } export function isMapLiteral(p) { return p.type == LiteralPatternType.MAP; } export class FunctionCallPattern extends BasePattern { constructor(fnName, args) { super(); this.isAsync = false; this.fnName = fnName; this.arguments = args; } asAsync() { this.isAsync = true; return this; } toString() { let s = ''; if (this.arguments.length > 0) { const args = []; this.arguments.forEach((bp) => { args.push(bp.toString()); }); s = `${this.fnName}(${args.join(', ')})`; } else { s = `${this.fnName}()`; } s = s.concat(this.hintsAsString()); if (this.isAsync) { return `await ${s}`; } else { return s; } } } export function isFunctionCallPattern(p) { return p instanceof FunctionCallPattern; } export class ExpressionPattern extends BasePattern { constructor(expression) { super(); this.expression = expression; } static async Validated(exprString) { const result = await _a.parse(`module Temp workflow Test { if (${exprString}) {} }`); if (result.parseResult.lexerErrors.length > 0) { throw new Error(result.parseResult.lexerErrors.join('\n')); } if (result.parseResult.parserErrors.length > 0) { throw new Error(result.parseResult.parserErrors.join('\n')); } return new _a(exprString); } toString() { const s = this.expression.toString(); return s.concat(this.hintsAsString()); } } _a = ExpressionPattern; ExpressionPattern.services = createAgentlangServices(EmptyFileSystem); ExpressionPattern.doParse = parseHelper(_a.services.Agentlang); ExpressionPattern.parse = (input) => _a.doParse(input, { validation: true }); export function isExpressionPattern(p) { return p instanceof ExpressionPattern; } export class GroupExpressionPattern extends BasePattern { constructor(expr) { super(); this.expression = expr; } toString() { return `(${this.expression.toString()})`; } } export function isGroupExpressionPattern(p) { return p instanceof GroupExpressionPattern; } export class NegExpressionPattern extends BasePattern { constructor(expr) { super(); this.expression = expr; } toString() { return `-${this.expression.toString}`; } } export class NotExpressionPattern extends BasePattern { constructor(expr) { super(); this.expression = expr; } toString() { return `not(${this.expression.toString})`; } } export function isNegExpressionPattern(p) { return p instanceof NegExpressionPattern; } export function isNotExpressionPattern(p) { return p instanceof NotExpressionPattern; } export class ReferencePattern extends BasePattern { constructor(record, member) { super(); this.record = record; this.member = member; } toString() { return `${this.record}.${this.member}`.concat(this.hintsAsString()); } } export function isReferencePattern(p) { return p instanceof ReferencePattern; } export class CrudPattern extends BasePattern { constructor(recordName) { super(); this.isQuery = false; this.isQueryUpdate = false; this.isCreate = false; this.recordName = recordName; this.attributes = []; if (recordName.endsWith('?')) { this.isQuery = true; } else { this.isCreate = true; } } addAttribute(n, p, op) { this.attributes.push({ name: n, op: op, value: p }); if (this.recordName.endsWith('?')) { this.recordName = this.recordName.substring(0, this.recordName.length - 1); } this.flagType(); return this; } removeAttribute(n) { const idx = this.attributes.findIndex((ap) => { return n == ap.name; }); if (idx >= 0) { this.attributes.splice(idx, 1); } this.flagType(); return this; } addInto(alias, attr) { if (this.into === undefined) { this.into = new Map(); } this.into.set(alias, attr); return this; } removeInto(alias) { if (this.into) { this.into.delete(alias); } return this; } resetInto(into) { this.into = into; return this; } hasInto() { if (this.into && this.into.size > 0) { return true; } else { return false; } } flagType() { let hasq = false; let hasc = false; for (let i = 0; i < this.attributes.length; ++i) { if (hasq && hasc) break; const ap = this.attributes[i]; hasq = ap.name.endsWith('?'); if (!hasc) hasc = !hasq; } if (hasq && hasc) { this.isQueryUpdate = true; this.isQuery = false; this.isCreate = false; } else if (hasc) { this.isCreate = true; this.isQuery = false; this.isQueryUpdate = false; } else { this.isQuery = hasq; this.isCreate = false; this.isQueryUpdate = false; } } addRelationship(n, p) { if (this.relationships === undefined) { this.relationships = new Map(); } this.relationships.set(n, p); return this; } removeRelationship(n) { if (this.relationships) { this.relationships.delete(n); } return this; } attributesAsString() { const result = []; this.attributes.forEach((ap) => { result.push(`${ap.name}${ap.op ? ap.op : ''} ${ap.value.toString()}`); }); const s = result.join(', '); return `{${s}}`; } relationshipsAsString() { if (this.relationships !== undefined) { const result = []; this.relationships.forEach((p, n) => { const ps = p instanceof Array ? `[${patternsToString(p, ',')}]` : p.toString(); result.push(`${n} ${ps}`); }); return result.join(','); } else { return undefined; } } getNormalizedRecordName() { return escapeQueryName(this.recordName); } intoAsString() { if (this.into) { const ss = new Array(); this.into.forEach((attr, alias) => { ss.push(`${alias} ${attr}`); }); return `@into { ${ss.join(',\n')} }`; } return undefined; } toString() { let s = `{${this.recordName} ${this.attributesAsString()}`; const rs = this.relationshipsAsString(); if (rs) { s = s.concat(`,${rs}`); } const ins = this.intoAsString(); if (ins) { s = s.concat(`,${ins}`); } return s.concat('}', this.hintsAsString()); } } export function isCrudPattern(p) { return p instanceof CrudPattern; } export function isCreatePattern(p) { return isCrudPattern(p) && p.isCreate; } export function isQueryPattern(p) { return isCrudPattern(p) && p.isQuery; } export function isQueryUpdatePattern(p) { return isCrudPattern(p) && p.isQueryUpdate; } export class ForEachPattern extends BasePattern { constructor(variable, source) { super(); this.variable = variable ? variable : 'X'; this.source = source ? source : LiteralPattern.EmptyArray; this.body = []; } addPattern(p) { this.body.push(p); return this; } removePattern(index) { this.body.splice(index, 1); return this; } setPatternAt(p, index) { this.body[index] = p; return this; } removePatternAt(index) { this.body.splice(index, 1); return this; } getPatternAt(index) { return this.body[index]; } setVariable(s) { this.variable = s; return this; } setSourcePattern(p) { this.source = p; return this; } toString() { if (this.source === undefined || this.variable === undefined) { throw new Error('`for` requires variable and source-pattern'); } let s = `for ${this.variable} in ${this.source.toString()}`; s = s.concat(`{${patternsToString(this.body)}}`); return s.concat(this.hintsAsString()); } } export function isForEachPattern(p) { return p instanceof ForEachPattern; } export class IfPattern extends BasePattern { constructor(condition) { super(); this.condition = condition ? condition : IfPattern.True; this.body = []; } isEmpty() { if (this.condition === IfPattern.True && this.body.length === 0) { return true; } else { return false; } } addPattern(p) { this.body.push(p); return this; } removePattern(index) { this.body.splice(index, 1); return this; } setPatternAt(p, index) { this.body[index] = p; return this; } removePatternAt(index) { this.body.splice(index, 1); return this; } getPatternAt(index) { return this.body[index]; } setConditionPattern(p) { this.condition = p; return this; } setElse(elseBody) { this.elseBody = elseBody ? elseBody : new Array(); return this; } removeElse() { this.elseBody = undefined; return this; } toString() { let s = `if(${this.condition.toString()}) {`; s = s.concat(patternsToString(this.body), '}'); if (this.elseBody) { if (this.elseBody.length == 1 && this.elseBody[0] instanceof IfPattern) { s = s.concat(` else ${this.elseBody[0].toString()}`); } else { s = s.concat(` else {${patternsToString(this.elseBody)}}`); } } return s.concat(this.hintsAsString()); } } IfPattern.True = new LiteralPattern(LiteralPatternType.BOOLEAN, true); export function isIfPattern(p) { return p instanceof IfPattern; } export class CasePattern extends BasePattern { constructor(condition, body) { super(); this.condition = condition; this.body = body; } static async FromString(s) { var _b; const ss = s.trimStart(); if (ss.startsWith('case')) { const m = await parseModule(`module T\ndecision D {\n${ss}}`); const d = m.defs[0]; if (isDecisionDefinition(d) && d.body) { const c = d.body.cases[0]; const b = await introspect(((_b = c.statements[0].$cstNode) === null || _b === void 0 ? void 0 : _b.text) || ''); return new CasePattern(new ExpressionPattern(c.cond), b[0]); } else { throw new Error(`Failed to parse ${s}`); } } throw new Error(`Not a case expression - ${s}`); } toString() { return `case (${this.condition.toString()}) { ${this.body.toString()} }`; } } export function isCasePattern(p) { return p instanceof CasePattern; } export function newCreatePattern(recName) { const cp = new CrudPattern(recName); cp.isCreate = true; return cp; } export function newQueryPattern(recName, forQueryUpdate = false) { recName = recName.charAt(recName.length - 1) == '?' ? recName : recName + '?'; const cp = new CrudPattern(recName); cp.isCreate = false; if (forQueryUpdate) { cp.isQueryUpdate = true; } else { cp.isQuery = true; } return cp; } export function newQueryUpdatePattern(recName) { return newQueryPattern(recName, true); } export class DeletePattern extends BasePattern { constructor(pattern) { super(); this.pattern = pattern; } toString() { return `delete ${this.pattern.toString()}`.concat(this.hintsAsString()); } } export class ReturnPattern extends BasePattern { constructor(pattern) { super(); this.pattern = pattern; } toString() { return `return ${this.pattern.toString()}`.concat(this.hintsAsString()); } } export class FullTextSearchPattern extends BasePattern { constructor(name, query, options) { super(); this.name = name; this.query = query; this.options = options; } toString() { const ops = this.options ? this.options.toString() : ''; return `{${this.name} ${this.query.toString()} ${ops}}`; } } export function isDeletePattern(p) { return p instanceof DeletePattern; } export function newDeletePattern(recName) { const qp = newQueryPattern(recName); return new DeletePattern(qp); } function patternsToString(body, sep = ';\n') { return body .map((p) => { return p.toString(); }) .join(sep); } export class FlowStepPattern extends BasePattern { constructor(first, next, condition) { super(); this.first = first; this.next = next; this.condition = condition ? trimQuotes(condition) : undefined; } static Parse(s) { const parts = s.trim().split(' '); const first = parts[0]; if (parts[1] == '-->') { if (parts.length == 3) { return new FlowStepPattern(first, parts[2]); } else { return new FlowStepPattern(first, parts[3], parts[2]); } } else { throw new Error(`Invalid flow-step format in ${s}`); } } toString() { if (this.condition) { return `${this.first} --> "${this.condition}" ${this.next}`; } else { return `${this.first} --> ${this.next}`; } } } //# sourceMappingURL=syntax.js.map