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
143 lines (132 loc) • 3.95 kB
text/typescript
import { logger } from './logger.js';
import { now, splitRefs } from './util.js';
import { isNodeEnv } from '../utils/runtime.js';
import { setModuleFnFetcher } from './defs.js';
let dirname: any = undefined;
let sep: any = undefined;
if (isNodeEnv) {
const p = await import('path');
dirname = p.dirname;
sep = p.sep;
} else {
sep = '/';
dirname = (s: string): string => {
const idx = s.lastIndexOf(sep);
if (idx > 0) {
return s.substring(0, idx);
} else {
return s;
}
};
}
const importedModules = new Map<string, any>();
// Usage: importModule("./mymodels/acme.js")
export async function importModule(path: string, name: string, moduleFileName?: string) {
if (isNodeEnv) {
if (importedModules.has(name)) {
logger.warn(`Alias '${name}' will overwrite a previously imported module`);
}
if (moduleFileName) {
let s: string = dirname(moduleFileName);
if (s.startsWith('./')) {
s = s.substring(2);
} else if (s == '.') {
s = process.cwd();
}
path = `${s}${sep}${path}`;
}
if (!(path.startsWith(sep) || path.startsWith('.'))) {
path = process.cwd() + sep + path;
}
const m = await import(/* @vite-ignore */ path);
importedModules.set(name, m);
// e.g of dynamic fn-call:
//// let f = eval("(a, b) => m.add(a, b)");
//// console.log(f(10, 20))
return m;
} else {
return {};
}
}
export function moduleImported(moduleName: string): boolean {
return importedModules.has(moduleName);
}
function maybeEvalFunction(fnName: string): Function | undefined {
try {
return eval(fnName);
} catch (reason: any) {
logger.debug(reason);
return undefined;
}
}
async function invokeBuiltInFn(fnName: string, args: Array<any> | null, isAsync: boolean = false) {
if (fnName == 'now') {
return now();
} else if (fnName == 'uuid') {
return crypto.randomUUID();
} else {
const pf: Function | undefined = maybeEvalFunction(fnName);
if (pf instanceof Function) {
if (args === null) {
if (isAsync) return await pf();
else return pf();
} else {
if (isAsync) return await pf(...args.slice(0, args.length - 1));
else return pf(...args.slice(0, args.length - 1));
}
} else {
throw new Error(`Failed to invoke function - ${fnName}`);
}
}
}
export async function invokeModuleFn(
fqFnName: string,
args: Array<any> | null,
isAsync: boolean = false
): Promise<any> {
try {
const refs: string[] = splitRefs(fqFnName);
if (refs.length == 1) {
if (isAsync) {
return await invokeBuiltInFn(refs[0], args, isAsync);
} else {
return invokeBuiltInFn(refs[0], args);
}
}
const mname = refs[0];
const m = importedModules.get(mname);
if (m !== undefined) {
const f = m[refs[1]];
if (f !== undefined) {
if (args === null)
if (isAsync) {
return await f();
} else return f();
else if (isAsync) {
return await f(...args);
} else return f(...args);
} else throw new Error(`Function not found - ${fqFnName}`);
} else throw new Error(`JavaScript module ${refs[0]} not found`);
} catch (reason: any) {
const pf: Function | undefined = maybeEvalFunction(fqFnName);
if (pf instanceof Function) {
if (args === null) {
if (isAsync) return await pf();
else return pf();
} else {
if (isAsync) return await pf(...args.slice(0, args.length - 1));
else return pf(...args.slice(0, args.length - 1));
}
} else {
throw new Error(reason);
}
}
}
export function getModuleFn(fqFnName: string): Function | undefined {
const refs: string[] = splitRefs(fqFnName);
const m = importedModules.get(refs[0]);
if (m !== undefined) {
return m[refs[1]];
} else return undefined;
}
setModuleFnFetcher(getModuleFn);