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

493 lines 18.6 kB
import { isPattern, isStatement, isWorkflowDefinition, } from '../language/generated/ast.js'; import { parseModule, parseStatement } from '../language/parser.js'; import { ExecGraph, ExecGraphNode, ExecGraphWalker, SubGraphType } from './defs.js'; import { DocEventName, Environment, evaluateExpression, evaluatePattern, evaluateStatement, handleAgentInvocation, handleOpenApiEvent, maybeBindStatementResultToAlias, maybeDeleteQueriedInstances, PatternHandler, setEvaluateFn, setParseAndEvaluateStatementFn, } from './interpreter.js'; import { fetchModule, getWorkflowForEvent, isAgentEvent, isAgentEventInstance, isEmptyWorkflow, isEventInstance, RecordType, } from './module.js'; import { flushMonitoringData } from './modules/core.js'; import { isOpenApiEventInstance, isOpenApiModule } from './openapi.js'; import { isMonitoringEnabled } from './state.js'; import { escapeQueryName, isCoreDefinition, isCoreModule, isFqName, makeFqName, nameToPath, } from './util.js'; const GraphCache = new Map(); export async function generateExecutionGraph(eventName) { const cg = GraphCache.get(eventName); if (cg) return cg; const wf = getWorkflowForEvent(eventName); const parts = nameToPath(eventName); const moduleName = parts.hasModule() ? parts.getModuleName() : undefined; if (!isEmptyWorkflow(wf)) { const g = (await graphFromStatements(wf.statements, moduleName)).setEventName(eventName); if (g.canCache()) GraphCache.set(eventName, g); return g; } return undefined; } class GraphGenerator extends PatternHandler { constructor() { super(...arguments); this.graph = new ExecGraph(); } genericHandler(env) { this.graph.pushNode(new ExecGraphNode(env.getActiveUserData())); } async handleExpression(_, env) { this.genericHandler(env); } async handleCrudMap(crudMap, env) { const parts = nameToPath(crudMap.name); const moduleName = parts.hasModule() ? parts.getModuleName() : env.getActiveModuleName(); const crudName = makeFqName(moduleName, parts.getEntryName()); if (crudName == DocEventName) { return this.genericHandler(env); } if (isOpenApiModule(moduleName)) { return this.genericHandler(env); } const module = fetchModule(moduleName); const record = module.getRecord(escapeQueryName(parts.getEntryName())); if (record.type == RecordType.EVENT) { if (isAgentEvent(record)) { this.graph.pushNode(new ExecGraphNode(env.getActiveUserData(), -2, SubGraphType.AGENT)); this.graph.setHasAgents(true); return; } else { const g = await generateExecutionGraph(crudName); if (g) { return this.addSubGraph(SubGraphType.EVENT, g, env); } } } this.genericHandler(env); } async handleForEach(forEach, env) { const handler = new GraphGenerator(); const srcEnv = Environment.from(env).setActiveUserData(forEach.src); await evaluatePattern(forEach.src, srcEnv, handler); const srcg = handler.getGraph(); const g = await graphFromStatements(forEach.statements, env.getActiveModuleName()); srcg.pushSubGraph(g); this.addSubGraph(SubGraphType.FOR_EACH, srcg, env); } async handleIf(ifStmt, env) { const handler = new GraphGenerator(); await handler.handleExpression(ifStmt.cond, Environment.from(env).setActiveUserData(ifStmt.cond)); const cond = handler.getGraph(); const conseq = await graphFromStatements(ifStmt.statements, env.getActiveModuleName()); cond.pushSubGraph(conseq); if (ifStmt.else !== undefined) { const alter = await graphFromStatements(ifStmt.else.statements, env.getActiveModuleName()); cond.pushSubGraph(alter); } else { cond.pushSubGraph(ExecGraph.Empty); } this.addSubGraph(SubGraphType.IF, cond, env); } async handleSubPattern(subGraphType, pat, env) { const newEnv = Environment.from(env).setActiveUserData(pat); const handler = new GraphGenerator(); await evaluatePattern(pat, newEnv, handler); this.addSubGraph(subGraphType, handler.getGraph(), env); } async handleDelete(del, env) { this.handleSubPattern(SubGraphType.DELETE, del.pattern, env); } async handlePurge(purge, env) { this.handleSubPattern(SubGraphType.PURGE, purge.pattern, env); } async handleFullTextSearch(_, env) { this.genericHandler(env); } async handleReturn(ret, env) { this.handleSubPattern(SubGraphType.RETURN, ret.pattern, env); } getGraph() { return this.graph; } addSubGraph(subGraphType, g, env) { this.graph.pushSubGraph(g); this.graph.pushNode(new ExecGraphNode(env.getActiveUserData(), this.graph.getLastSubGraphIndex(), subGraphType)); } } async function graphFromStatements(stmts, activeModuleName) { const handler = new GraphGenerator(); const env = new Environment(); if (activeModuleName) { env.switchActiveModuleName(activeModuleName); } for (let i = 0; i < stmts.length; ++i) { const stmt = stmts[i]; env.setActiveUserData(stmt); await evaluatePattern(stmt.pattern, env, handler); } return handler.getGraph().setActiveModuleName(activeModuleName); } function makeStatementsExecutor(execGraph, triggeringNode) { return async (stmts, env) => { const g = await graphFromStatements(stmts, env.getActiveModuleName()); if (execGraph && triggeringNode) { execGraph.pushSubGraph(g); triggeringNode.subGraphIndex = execGraph.getLastSubGraphIndex(); } await executeGraph(g, env); return env.getLastResult(); }; } export async function executeGraph(execGraph, env) { const activeModuleName = execGraph.getActiveModuleName(); env.setEventExecutor(executeEventHelper); let oldModule = undefined; if (activeModuleName) { oldModule = env.switchActiveModuleName(activeModuleName); } const coreMod = activeModuleName ? isCoreModule(activeModuleName) : false; const monitoringEnabled = !coreMod && isMonitoringEnabled(); try { const walker = new ExecGraphWalker(execGraph); while (walker.hasNext()) { if (env.isMarkedForReturn()) { break; } const node = walker.nextNode(); const monitorIncr = monitoringEnabled && node.subGraphIndex !== -1 && (node.subGraphType == SubGraphType.AGENT || node.subGraphType == SubGraphType.EVENT); if (node.codeStr && monitoringEnabled) { if (!isSystemCrudPattern(node.code, activeModuleName)) { if (monitorIncr) { env.incrementMonitor(); } env.appendEntryToMonitor(node.codeStr); } } try { if (node.subGraphIndex == -1) { await evaluateStatement(node.code, env); } else { if (node.subGraphType == SubGraphType.AGENT) { await executeAgent(node, execGraph, env); } else { const subg = execGraph.fetchSubGraphAt(node.subGraphIndex); switch (node.subGraphType) { case SubGraphType.EVENT: await evaluateStatement(node.code, env); break; case SubGraphType.IF: { const newEnv = new Environment(`${env.name}-if`, env); await executeIfSubGraph(subg, newEnv); env.setLastResult(newEnv.getLastResult()); break; } case SubGraphType.FOR_EACH: { const newEnv = new Environment(`${env.name}-forEach`, env); await executeForEachSubGraph(subg, node, newEnv); env.setLastResult(newEnv.getLastResult()); break; } case SubGraphType.DELETE: await executeDeleteSubGraph(subg, node, env); break; case SubGraphType.PURGE: await executePurgeSubGraph(subg, node, env); break; case SubGraphType.RETURN: await executeReturnSubGraph(subg, env); return; default: throw new Error(`Invalid sub-graph type: ${node.subGraphType}`); } } maybeSetAlias(node, env); } } catch (reason) { if (monitoringEnabled) env.setMonitorEntryError(reason); throw reason; } finally { if (monitoringEnabled) { if (monitorIncr) env.decrementMonitor(); env.setMonitorEntryResult(env.getLastResult()); } } } } finally { if (oldModule) { env.switchActiveModuleName(oldModule); } } } function isSystemCrudPattern(code, activeModuleName) { if (isStatement(code)) { return isSystemCrudPattern(code.pattern, activeModuleName); } else if (isPattern(code)) { const crud = code.crudMap; if (crud) { if (isFqName(crud.name)) return isCoreDefinition(crud.name); else if (activeModuleName) return isCoreModule(activeModuleName); } } return false; } async function evaluateFirstPattern(g, env) { await evaluatePattern(g.getRootNodes()[0].code, env); } async function executeForEachSubGraph(subGraph, triggeringNode, env) { var _a; await evaluateFirstPattern(subGraph, env); const rs = env.getLastResult(); if (rs.length > 0) { const stmt = triggeringNode.code; const loopVar = ((_a = stmt.pattern.forEach) === null || _a === void 0 ? void 0 : _a.var) || 'x'; const loopEnv = new Environment('for-each-body-env', env); const loopg = subGraph.fetchForEachBodySubGraph(); const finalResult = new Array(); for (let i = 0; i < rs.length; ++i) { loopEnv.bind(loopVar, rs[i]); await executeGraph(loopg, loopEnv); finalResult.push(loopEnv.getLastResult()); } env.setLastResult(finalResult); } else { env.setLastResult([]); } } async function executeIfSubGraph(subGraph, env) { await evaluateExpression(subGraph.getRootNodes()[0].code, env); const newEnv = new Environment('cond-env', env); if (env.getLastResult()) { const conseq = subGraph.fetchIfConsequentSubGraph(); await executeGraph(conseq, newEnv); } else { const alter = subGraph.fetchIfAlternativeSubGraph(); if (alter) { if (ExecGraph.isEmpty(alter)) { newEnv.setLastResult(false); } else { await executeGraph(alter, newEnv); } } } env.setLastResult(newEnv.getLastResult()); } async function executeAgent(triggeringNode, execGraph, env) { await env.callWithStatementsExecutor(makeStatementsExecutor(execGraph, triggeringNode), async () => { await evaluateStatement(triggeringNode.code, env); return env.getLastResult(); }); } async function executeReturnSubGraph(subGraph, env) { await evaluateFirstPattern(subGraph, env); env.markForReturn(); } async function executeDeleteSubGraph(subGraph, node, env) { const newEnv = new Environment(`delete-env`, env).setInDeleteMode(true); await evaluateFirstPattern(subGraph, newEnv); await maybeDeleteQueriedInstances(newEnv, env, false); maybeSetAlias(node, env); } async function executePurgeSubGraph(subGraph, node, env) { const newEnv = new Environment(`purge-env`, env).setInDeleteMode(true); await evaluateFirstPattern(subGraph, newEnv); await maybeDeleteQueriedInstances(newEnv, env, true); maybeSetAlias(node, env); } export async function executeEvent(eventInstance, continuation, activeEnv, kernelCall) { const env = new Environment(eventInstance.name + '.env', activeEnv); env.setStatementsExecutor(executeStatementsHelper); let txnRolledBack = false; try { if (isEventInstance(eventInstance)) { if (kernelCall) { env.setInKernelMode(true); } env.setActiveEvent(eventInstance); await executeEventHelper(eventInstance, env); } else if (isAgentEventInstance(eventInstance)) { await handleAgentInvocation(eventInstance, env); } const r = env.getLastResult(); if (continuation) continuation(r); return r; } catch (err) { if (env && env.hasHandlers()) { throw err; } else { if (env !== undefined && activeEnv === undefined) { await env.rollbackAllTransactions().then(() => { txnRolledBack = true; }); } throw err; } } finally { if (!txnRolledBack && env !== undefined && activeEnv === undefined) { await env.commitAllTransactions(); } if (isMonitoringEnabled()) { await flushMonitoringData(eventInstance.getId()); } } } export async function executeEventHelper(eventInstance, env) { if (isOpenApiEventInstance(eventInstance)) { env = env || new Environment(); await handleOpenApiEvent(eventInstance, env); return env.getLastResult(); } const fqn = eventInstance.getFqName(); let isLocalEnv = false; if (env === undefined) { env = new Environment(`${fqn}-env`); isLocalEnv = true; } let g; if (!isAgentEventInstance(eventInstance)) { g = await generateExecutionGraph(fqn); if (!g) { throw new Error(`Failed to generate graph for event ${fqn}`); } } const oldModuleName = env.switchActiveModuleName(eventInstance.moduleName); env.bind(eventInstance.name, eventInstance); try { if (g) { await executeGraph(g, env); } else { if (isMonitoringEnabled()) { env.appendEntryToMonitor(`{${eventInstance.getFqName()} {message "${eventInstance.lookup('message')}"}}`); } await handleAgentInvocation(eventInstance, env); } if (isLocalEnv) { await env.commitAllTransactions(); } return env.getLastResult(); } catch (err) { if (isLocalEnv) { await env.rollbackAllTransactions(); } throw err; } finally { if (!isLocalEnv) env.switchActiveModuleName(oldModuleName); } } export async function executeStatement(stmt, env, activeModule) { return await executeStatements([stmt], env, activeModule); } export async function executeStatements(stmts, env, activeModule) { const mod = await parseModule(`module Temp\nworkflow TempEvent { ${stmts.join(';')} }`); if (isWorkflowDefinition(mod.defs[0])) { return await executeStatementsHelper(mod.defs[0].statements, env, activeModule); } else { throw new Error('Failed to extract workflow-statement'); } } async function executeStatementsHelper(stmts, env, activeModule) { const g = await graphFromStatements(stmts); let isLocalEnv = false; if (env === undefined) { env = new Environment(`stmt-exec-env`); isLocalEnv = true; } let oldModuleName = undefined; if (activeModule) { oldModuleName = env.switchActiveModuleName(activeModule); } try { await executeGraph(g, env); if (isLocalEnv) { await env.commitAllTransactions(); } return env.getLastResult(); } catch (err) { if (isLocalEnv) { await env.rollbackAllTransactions(); } throw err; } finally { if (oldModuleName) { env.switchActiveModuleName(oldModuleName); } } } async function executeStatementHelper(stmt, env) { return await executeStatementsHelper([stmt], env); } export async function parseAndExecuteStatement(stmtString, activeUserId, actievEnv) { const env = actievEnv ? actievEnv : new Environment(); if (activeUserId) { env.setActiveUser(activeUserId); } let commit = true; try { const stmt = await parseStatement(stmtString); if (stmt) { await executeStatementHelper(stmt, env); return env.getLastResult(); } else { commit = false; } } catch (err) { commit = false; throw err; } finally { if (!actievEnv) { if (commit) { await env.commitAllTransactions(); } else { await env.rollbackAllTransactions(); } } } } function maybeSetAlias(node, env) { const stmt = node.code; const hints = stmt.hints; if (hints && hints.length > 0) { maybeBindStatementResultToAlias(hints, env); } } export function enableExecutionGraph() { const e = setEvaluateFn(executeEvent); const es = setParseAndEvaluateStatementFn(parseAndExecuteStatement); return { evaluate: e, parseAndEvaluateStatement: es }; } export function disableExecutionGraph(oldFns) { if (oldFns.evaluate && oldFns.parseAndEvaluateStatement) { setEvaluateFn(oldFns.evaluate); setParseAndEvaluateStatementFn(oldFns.parseAndEvaluateStatement); return true; } return false; } //# sourceMappingURL=exec-graph.js.map