UNPKG

daggerai

Version:

A simple and powerful Typescript based agent framework to help businesses thrive in the AI Agent revolution.

118 lines 4.37 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Squad = void 0; const events_1 = require("events"); const nanoid_1 = require("nanoid"); const typescript_graph_1 = require("typescript-graph"); const helpers_1 = require("./helpers"); class Squad { graph = new typescript_graph_1.DirectedAcyclicGraph(); env = {}; queue = []; order = []; nodes = []; history = []; // additional instructions the user can send to the squad inputs = []; instructions = ''; events = new events_1.EventEmitter(); verbose = false; constructor(params = {}) { this.verbose = params.verbose || false; } async evaluate(params) { this.inputs = params.inputs; this.instructions = params.instructions || ''; // find the nodes with no incoming edges let inDegree = {}; for (const node of this.nodes) { inDegree[node.id] = node.adjancentFrom.length; } // the queue starts with the nodes that have no incoming edges this.queue = Object.keys(inDegree).filter(id => inDegree[id] === 0); // the order the nodes were executed this.order = []; // Keep running the loop until there are no more nodes to execute while (true) { const nextNode = this.findNextNode(this.queue); if (!nextNode) { break; } // Remove the next node from the queue this.queue.splice(this.queue.indexOf(nextNode.id), 1); if (nextNode.type === 'input') { const inputNode = nextNode; if (!this.inputs) { throw new Error('Inputs are required'); } const input = this.inputs.find(i => (0, helpers_1.removeDiacritics)(i.name).toLowerCase() === (0, helpers_1.removeDiacritics)(inputNode.name).toLowerCase()); inputNode.output = input?.value || ''; } if (nextNode.type === 'task') { const taskNode = nextNode; // Add the next node to the order array this.order.push(taskNode); // Executes the node const taskResponse = await taskNode.execute(this); this.env[taskNode.id] = taskResponse; } this.history.push(nextNode.id); // Add the IDs of the nodes that the current node is adjacent to to the queue for (const id of nextNode.adjacentTo) { if (this.history.includes(id) || this.queue.includes(id)) { continue; } this.queue.push(id); } } this.events.emit('squad.finished', { name: 'Squad', output: Object.values(this.env).join('\n\n'), }); // Return the environment object containing the results of all executed tasks return this.env; } recalculateInDegree(id) { const node = this.nodes.find(t => t.id === id); const dependencies = node.adjancentFrom; return dependencies.filter(d => !this.history.includes(d)).length; } findNextNode(ids) { for (let id of ids) { const degree = this.recalculateInDegree(id); if (degree === 0) { return this.nodes.find(t => t.id === id); } } return null; } connect(from, to) { const fromNode = this.nodes.find(t => t.id === from.id); const toNode = this.nodes.find(t => t.id === to.id); if (!fromNode || !toNode) { throw new Error('Node not found'); } fromNode.adjacentTo.push(to.id); toNode.adjancentFrom.push(from.id); this.graph.addEdge(from.graphId, to.graphId); } add(node) { if (!node.id) { node.id = (0, nanoid_1.nanoid)(); } node.graphId = this.graph.insert(node.id); this.nodes.push(node); } sortedNodes() { return this.graph .topologicallySortedNodes() .map(n => this.nodes.find(t => t.id === n)); } nodesById(ids) { const allNodes = this.sortedNodes(); return ids.map(t => allNodes.find(n => n.id === t)); } } exports.Squad = Squad; //# sourceMappingURL=squad.js.map