@agent-graph/core
Version:
A lightweight AI Agent orchestration solution
126 lines (125 loc) • 5.1 kB
JavaScript
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
/**
* Lifecycle: run(init) -> superstep() -> interrupt() -> superstep() -> exit() -> ... -> shutdown()
* */
export class BuiltGraph {
constructor({ builder, context, checkpointer, }) {
var _a;
this.running = false;
this.version = 1;
this.interruptVectorTable = [];
this.shutdownHooks = [];
this.computedListeners = [];
this.context = context;
this.builder = builder;
this.checkpointer = checkpointer;
(_a = this.checkpointer) === null || _a === void 0 ? void 0 : _a.setVersion(this.version);
// runtime methods
this.exit = this.exit.bind(this);
this.interrupt = this.interrupt.bind(this);
this.addShutdownHook = this.addShutdownHook.bind(this);
}
// todo: priority queue ...
interrupt(interrupt) {
this.interruptVectorTable.push(interrupt);
}
exit(status) {
this.running = false;
}
addShutdownHook(hook) {
this.shutdownHooks.push(hook);
}
shutdown() {
return __awaiter(this, void 0, void 0, function* () {
const hook = this.shutdownHooks.pop();
if (!hook)
return;
yield hook();
});
}
get runtime() {
return {
context: this.context,
version: this.version,
exit: this.exit,
interrupt: this.interrupt,
addShutdownHook: this.addShutdownHook,
};
}
onComputed(listener) {
this.computedListeners.push(listener);
}
activeAllVertices() {
for (const vertex of this.builder.vertices.values()) {
vertex.active();
}
}
setVertexStates(states) {
for (const [id, state] of Object.entries(states)) {
const vertex = this.builder.vertices.get(id);
vertex === null || vertex === void 0 ? void 0 : vertex.setState(state);
}
}
getVertexStates() {
const states = {};
for (const vertex of this.builder.vertices.values()) {
states[vertex.id] = vertex.state;
}
return states;
}
// single vertex compute
compute(vertexId, inputProps) {
return __awaiter(this, void 0, void 0, function* () {
const vertex = this.builder.vertices.get(vertexId);
if (!vertex)
return [];
const getOutEdges = this.builder.edges.get(vertex.id);
const props = yield vertex.compute(inputProps, this.runtime);
this.computedListeners.forEach((listener) => listener(vertexId, props));
const edges = getOutEdges
? (yield getOutEdges(props, vertex.state, this.runtime)).map((v) => v.id)
: [];
if (vertex.isWaiting) {
return [{ next: vertexId, props: inputProps }];
}
const steps = edges.map((next) => ({ next, props }));
return steps;
});
}
superstep(state) {
return __awaiter(this, void 0, void 0, function* () {
const promises = state.map(({ next, props }) => this.compute(next, props));
return (yield Promise.all(promises)).flat();
});
}
run(initialSteps_1) {
return __awaiter(this, arguments, void 0, function* (initialSteps, initialStates = {}) {
var _a;
this.running = true;
let steps = initialSteps;
this.setVertexStates(initialStates);
this.activeAllVertices();
while (steps.length !== 0) {
// filter active vertices
const activeSteps = steps.filter(({ next }) => { var _a; return (_a = this.builder.vertices.get(next)) === null || _a === void 0 ? void 0 : _a.isActive; });
const otherSteps = steps.filter(({ next }) => { var _a; return !((_a = this.builder.vertices.get(next)) === null || _a === void 0 ? void 0 : _a.isActive); });
if (activeSteps.length === 0)
break;
const nextSteps = yield this.superstep(activeSteps);
steps = [...nextSteps, ...otherSteps];
yield ((_a = this.checkpointer) === null || _a === void 0 ? void 0 : _a.save(steps, this.getVertexStates()));
if (!this.running)
break;
}
yield this.shutdown();
});
}
}