@juspay/neurolink
Version:
The pipe layer of an AI nervous system: one interface connecting provider neurons to your application, across three inference types — generate, stream and decide. `decide` returns typed, calibrated judgements from a non-generative model (~400ms, ~$0.00002
479 lines (478 loc) • 17.6 kB
JavaScript
/**
* Network Orchestrator - High-level orchestration of agent networks
*
* The Orchestrator manages:
* - Network lifecycle (creation, execution, shutdown)
* - Multi-network coordination
* - Network-level policies and constraints
* - Resource management and scaling
*/
import { EventEmitter } from "events";
import { randomUUID } from "crypto";
import { AgentCoordinator } from "../coordination/coordinator.js";
import { MessageBus } from "../communication/message-bus.js";
import { logger } from "../../utils/logger.js";
/**
* Network Orchestrator - Central controller for agent networks
*/
export class NetworkOrchestrator {
neurolink;
networks = new Map();
networkInfo = new Map();
coordinators = new Map();
messageBus;
config;
emitter;
executionQueue = [];
// `void` admits the resolved placeholder used by streamNetwork to track
// an in-flight stream; only .size/.set/.delete are ever used on this map.
activeExecutions = new Map();
constructor(neurolink, config) {
this.neurolink = neurolink;
this.config = {
defaultMode: "autonomous",
maxConcurrentExecutions: 5,
defaultTimeout: 120000,
enableHierarchy: true,
maxHierarchyDepth: 3,
enableSharedMessageBus: true,
resourceLimits: {
maxNetworks: 10,
maxAgentsPerNetwork: 20,
maxTotalAgents: 100,
},
...config,
};
this.emitter = new EventEmitter();
this.messageBus = new MessageBus();
logger.info("[NetworkOrchestrator] Initialized", {
maxConcurrentExecutions: this.config.maxConcurrentExecutions,
enableHierarchy: this.config.enableHierarchy,
});
}
/**
* Create a new agent network
*/
async createNetwork(config, mode) {
// Check resource limits
if (this.config.resourceLimits?.maxNetworks &&
this.networks.size >= this.config.resourceLimits.maxNetworks) {
throw new Error("Maximum number of networks reached");
}
if (this.config.resourceLimits?.maxAgentsPerNetwork &&
config.agents.length > this.config.resourceLimits.maxAgentsPerNetwork) {
throw new Error(`Maximum agents per network (${this.config.resourceLimits.maxAgentsPerNetwork}) exceeded`);
}
if (this.config.resourceLimits?.maxTotalAgents) {
const currentTotalAgents = Array.from(this.networkInfo.values()).reduce((sum, info) => sum + info.agentCount, 0);
if (currentTotalAgents + config.agents.length >
this.config.resourceLimits.maxTotalAgents) {
throw new Error(`Maximum total agents (${this.config.resourceLimits.maxTotalAgents}) exceeded`);
}
}
// Create the network via NeuroLink
const network = await this.neurolink.createNetwork(config);
// Track network info
const info = {
id: network.id,
name: network.name,
state: "ready",
agentCount: config.agents.length,
mode: mode ?? this.config.defaultMode,
createdAt: Date.now(),
executionCount: 0,
childNetworkIds: [],
};
this.networkInfo.set(network.id, info);
this.networks.set(network.id, network);
// Create coordinator for the network
const coordinator = new AgentCoordinator({
strategy: "sequential",
maxConcurrency: 3,
});
for (const agent of network.getAllAgents()) {
coordinator.registerAgent(agent);
}
this.coordinators.set(network.id, coordinator);
this.emitter.emit("network:created", {
networkId: network.id,
name: network.name,
});
logger.info(`[NetworkOrchestrator] Network created: ${network.name}`, {
networkId: network.id,
agentCount: config.agents.length,
});
return network;
}
/**
* Create a hierarchical network
*/
async createHierarchicalNetwork(config, parentNetworkId) {
if (!this.config.enableHierarchy) {
throw new Error("Hierarchical networks are disabled");
}
// Check hierarchy constraints
if (parentNetworkId) {
const parentInfo = this.networkInfo.get(parentNetworkId);
if (!parentInfo) {
throw new Error(`Parent network not found: ${parentNetworkId}`);
}
// Check depth
let depth = 0;
let currentParent = parentInfo;
while (currentParent.parentNetworkId) {
depth++;
currentParent = this.networkInfo.get(currentParent.parentNetworkId);
if (depth >= this.config.maxHierarchyDepth) {
throw new Error(`Maximum hierarchy depth (${this.config.maxHierarchyDepth}) exceeded`);
}
}
}
const network = await this.createNetwork(config, config.supervisionMode ?? "hierarchical");
// Set up hierarchy relationships
if (parentNetworkId) {
const info = this.networkInfo.get(network.id);
info.parentNetworkId = parentNetworkId;
const parentInfo = this.networkInfo.get(parentNetworkId);
parentInfo.childNetworkIds.push(network.id);
}
return network;
}
/**
* Get a network by ID
*/
getNetwork(networkId) {
return this.networks.get(networkId);
}
/**
* Get network info
*/
getNetworkInfo(networkId) {
return this.networkInfo.get(networkId);
}
/**
* Get all networks
*/
getAllNetworks() {
return Array.from(this.networkInfo.values());
}
/**
* Execute a network
*/
async executeNetwork(networkId, input, options) {
const network = this.networks.get(networkId);
if (!network) {
throw new Error(`Network not found: ${networkId}`);
}
const info = this.networkInfo.get(networkId);
if (info.state === "paused") {
throw new Error(`Network is paused: ${networkId}`);
}
if (info.state === "shutdown") {
throw new Error(`Network is shut down: ${networkId}`);
}
if (info.state === "executing") {
// Queue the execution
return this.queueExecution({ networkId, input, options });
}
// Check concurrent execution limit
if (this.activeExecutions.size >= this.config.maxConcurrentExecutions) {
return this.queueExecution({ networkId, input, options });
}
return this.executeNetworkInternal(network, info, input, options);
}
/**
* Internal network execution
*/
async executeNetworkInternal(network, info, input, options) {
info.state = "executing";
info.executionCount++;
const executionPromise = (async () => {
try {
this.emitter.emit("network:execution:start", {
networkId: network.id,
input,
});
const result = await network.execute(input, {
...options,
timeout: options?.timeout ?? this.config.defaultTimeout,
});
info.lastExecutionAt = Date.now();
info.state = "ready";
this.emitter.emit("network:execution:complete", {
networkId: network.id,
result,
});
return result;
}
catch (error) {
info.state = "error";
this.emitter.emit("network:execution:error", {
networkId: network.id,
error: error instanceof Error ? error.message : String(error),
});
throw error;
}
finally {
this.activeExecutions.delete(network.id);
this.processExecutionQueue();
}
})();
this.activeExecutions.set(network.id, executionPromise);
return executionPromise;
}
/**
* Queue an execution request
*/
async queueExecution(request) {
return new Promise((resolve, reject) => {
const _queuedRequest = {
...request,
resolve,
reject,
};
this.executionQueue.push(_queuedRequest);
this.executionQueue.sort((a, b) => {
const priorityOrder = { high: 0, normal: 1, low: 2 };
return ((priorityOrder[a.priority ?? "normal"] ?? 1) -
(priorityOrder[b.priority ?? "normal"] ?? 1));
});
this.emitter.emit("execution:queued", { networkId: request.networkId });
});
}
/**
* Process queued executions
*/
async processExecutionQueue() {
while (this.executionQueue.length > 0 &&
this.activeExecutions.size < this.config.maxConcurrentExecutions) {
const request = this.executionQueue.shift();
const network = this.networks.get(request.networkId);
const info = this.networkInfo.get(request.networkId);
if (network && info && info.state !== "executing") {
// Fire-and-forget: executeNetworkInternal is NOT awaited so the while
// loop drains the entire queue synchronously before any launched
// execution sets info.state = "executing" (that happens at the first
// await inside executeNetworkInternal). This is intentional — it lets
// one queue-drain pass start multiple networks in parallel up to
// maxConcurrentExecutions.
this.executeNetworkInternal(network, info, request.input, request.options)
.then((result) => request.resolve?.(result))
.catch((err) => request.reject?.(err));
}
else if (request.reject) {
request.reject(new Error(`Network unavailable for execution: ${request.networkId}`));
}
}
}
/**
* Stream network execution
*/
async *streamNetwork(networkId, input, options) {
const network = this.networks.get(networkId);
if (!network) {
throw new Error(`Network not found: ${networkId}`);
}
const info = this.networkInfo.get(networkId);
if (info.state === "paused") {
throw new Error(`Network is paused: ${networkId}`);
}
if (info.state === "shutdown") {
throw new Error(`Network is shut down: ${networkId}`);
}
if (info.state === "executing") {
throw new Error(`Network is already executing: ${networkId}. Streaming does not support queuing.`);
}
if (this.activeExecutions.size >= this.config.maxConcurrentExecutions) {
throw new Error(`Maximum concurrent executions (${this.config.maxConcurrentExecutions}) reached. Streaming does not support queuing.`);
}
info.state = "executing";
info.executionCount++;
const streamPromise = Promise.resolve(); // placeholder to track in activeExecutions
this.activeExecutions.set(networkId, streamPromise);
try {
yield* network.stream(input, options);
info.lastExecutionAt = Date.now();
}
finally {
info.state = "ready";
this.activeExecutions.delete(networkId);
this.processExecutionQueue();
}
}
/**
* Execute hierarchical network with delegation
*/
async executeHierarchical(networkId, input, options) {
const network = this.networks.get(networkId);
const info = this.networkInfo.get(networkId);
if (!network || !info) {
throw new Error(`Network not found: ${networkId}`);
}
const traceId = randomUUID();
const trace = {
traceId,
steps: [],
routingDecisions: [],
startTime: Date.now(),
hierarchyLevel: 0,
childTraces: [],
};
// Calculate hierarchy level
let currentInfo = info;
while (currentInfo.parentNetworkId) {
trace.hierarchyLevel++;
trace.parentTraceId = currentInfo.parentNetworkId;
currentInfo = this.networkInfo.get(currentInfo.parentNetworkId);
}
// Execute main network
const result = await this.executeNetwork(networkId, input, options);
trace.steps = result.trace.steps;
trace.routingDecisions = result.trace.routingDecisions;
trace.endTime = Date.now();
// Execute child networks if needed based on delegation rules
for (const childId of info.childNetworkIds) {
const childNetwork = this.networks.get(childId);
if (childNetwork) {
const childTrace = await this.executeHierarchical(childId, { message: result.content, context: input.context }, options);
trace.childTraces?.push(childTrace);
}
}
return trace;
}
/**
* Pause a network
*/
pauseNetwork(networkId) {
const info = this.networkInfo.get(networkId);
if (info && info.state === "ready") {
info.state = "paused";
this.emitter.emit("network:paused", { networkId });
}
}
/**
* Resume a network
*/
resumeNetwork(networkId) {
const info = this.networkInfo.get(networkId);
if (info && info.state === "paused") {
info.state = "ready";
this.emitter.emit("network:resumed", { networkId });
}
}
/**
* Shutdown a network
*/
async shutdownNetwork(networkId) {
const info = this.networkInfo.get(networkId);
if (!info) {
return;
}
// Shutdown child networks first
for (const childId of info.childNetworkIds) {
await this.shutdownNetwork(childId);
}
// Remove from parent's child list
if (info.parentNetworkId) {
const parentInfo = this.networkInfo.get(info.parentNetworkId);
if (parentInfo) {
parentInfo.childNetworkIds = parentInfo.childNetworkIds.filter((id) => id !== networkId);
}
}
info.state = "shutdown";
this.networks.delete(networkId);
this.networkInfo.delete(networkId);
this.coordinators.delete(networkId);
this.emitter.emit("network:shutdown", { networkId });
logger.info(`[NetworkOrchestrator] Network shutdown: ${networkId}`);
}
/**
* Coordinate multiple networks
*/
async coordinateNetworks(networkIds, task, strategy = "parallel") {
const results = new Map();
switch (strategy) {
case "sequential":
case "pipeline": {
// Each network receives the previous network's output as its input
let currentInput = task;
for (const networkId of networkIds) {
const result = await this.executeNetwork(networkId, {
message: currentInput,
});
results.set(networkId, result);
currentInput = result.content;
}
break;
}
case "parallel": {
await Promise.all(networkIds.map(async (networkId) => {
const result = await this.executeNetwork(networkId, {
message: task,
});
results.set(networkId, result);
}));
break;
}
default:
throw new Error(`Unsupported coordination strategy: ${strategy}`);
}
return results;
}
/**
* Get orchestrator statistics
*/
getStats() {
const networksByState = {
idle: 0,
initializing: 0,
ready: 0,
executing: 0,
paused: 0,
error: 0,
shutdown: 0,
};
let totalExecutions = 0;
for (const info of this.networkInfo.values()) {
networksByState[info.state]++;
totalExecutions += info.executionCount;
}
return {
totalNetworks: this.networks.size,
activeExecutions: this.activeExecutions.size,
queuedExecutions: this.executionQueue.length,
totalExecutions,
networksByState,
};
}
/**
* Get the shared message bus
*/
getMessageBus() {
return this.messageBus;
}
/**
* Subscribe to orchestrator events
*/
on(event, handler) {
this.emitter.on(event, handler);
}
/**
* Unsubscribe from orchestrator events
*/
off(event, handler) {
this.emitter.off(event, handler);
}
/**
* Shutdown the orchestrator
*/
async shutdown() {
// Shutdown all networks
for (const networkId of this.networks.keys()) {
await this.shutdownNetwork(networkId);
}
// Shutdown message bus
this.messageBus.shutdown();
logger.info("[NetworkOrchestrator] Shutdown complete");
}
}