@juspay/neurolink 9.82.0 → 9.84.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/dist/agent/agent.d.ts +104 -0
- package/dist/agent/agent.js +401 -0
- package/dist/agent/agentNetwork.d.ts +87 -0
- package/dist/agent/agentNetwork.js +458 -0
- package/dist/agent/communication/index.d.ts +9 -0
- package/dist/agent/communication/index.js +9 -0
- package/dist/agent/communication/message-bus.d.ts +113 -0
- package/dist/agent/communication/message-bus.js +406 -0
- package/dist/agent/coordination/coordinator.d.ts +83 -0
- package/dist/agent/coordination/coordinator.js +598 -0
- package/dist/agent/coordination/index.d.ts +10 -0
- package/dist/agent/coordination/index.js +10 -0
- package/dist/agent/coordination/task-distributor.d.ts +113 -0
- package/dist/agent/coordination/task-distributor.js +585 -0
- package/dist/agent/index.d.ts +38 -0
- package/dist/agent/index.js +44 -0
- package/dist/agent/orchestration/index.d.ts +10 -0
- package/dist/agent/orchestration/index.js +10 -0
- package/dist/agent/orchestration/orchestrator.d.ts +114 -0
- package/dist/agent/orchestration/orchestrator.js +476 -0
- package/dist/agent/orchestration/topology.d.ts +164 -0
- package/dist/agent/orchestration/topology.js +520 -0
- package/dist/agent/prompts/routingPrompts.d.ts +63 -0
- package/dist/agent/prompts/routingPrompts.js +201 -0
- package/dist/browser/neurolink.min.js +377 -358
- package/dist/cli/commands/agent.d.ts +37 -0
- package/dist/cli/commands/agent.js +718 -0
- package/dist/cli/factories/commandFactory.d.ts +8 -0
- package/dist/cli/factories/commandFactory.js +116 -0
- package/dist/cli/loop/optionsSchema.d.ts +1 -1
- package/dist/cli/parser.js +4 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +19 -0
- package/dist/lib/agent/agent.d.ts +104 -0
- package/dist/lib/agent/agent.js +402 -0
- package/dist/lib/agent/agentNetwork.d.ts +87 -0
- package/dist/lib/agent/agentNetwork.js +459 -0
- package/dist/lib/agent/communication/index.d.ts +9 -0
- package/dist/lib/agent/communication/index.js +10 -0
- package/dist/lib/agent/communication/message-bus.d.ts +113 -0
- package/dist/lib/agent/communication/message-bus.js +407 -0
- package/dist/lib/agent/coordination/coordinator.d.ts +83 -0
- package/dist/lib/agent/coordination/coordinator.js +599 -0
- package/dist/lib/agent/coordination/index.d.ts +10 -0
- package/dist/lib/agent/coordination/index.js +11 -0
- package/dist/lib/agent/coordination/task-distributor.d.ts +113 -0
- package/dist/lib/agent/coordination/task-distributor.js +586 -0
- package/dist/lib/agent/index.d.ts +38 -0
- package/dist/lib/agent/index.js +45 -0
- package/dist/lib/agent/orchestration/index.d.ts +10 -0
- package/dist/lib/agent/orchestration/index.js +11 -0
- package/dist/lib/agent/orchestration/orchestrator.d.ts +114 -0
- package/dist/lib/agent/orchestration/orchestrator.js +477 -0
- package/dist/lib/agent/orchestration/topology.d.ts +164 -0
- package/dist/lib/agent/orchestration/topology.js +521 -0
- package/dist/lib/agent/prompts/routingPrompts.d.ts +63 -0
- package/dist/lib/agent/prompts/routingPrompts.js +202 -0
- package/dist/lib/index.d.ts +6 -0
- package/dist/lib/index.js +19 -0
- package/dist/lib/neurolink.d.ts +129 -0
- package/dist/lib/neurolink.js +276 -0
- package/dist/lib/processors/config/{fileTypes.js → fileExtensions.js} +1 -1
- package/dist/lib/processors/config/index.d.ts +2 -2
- package/dist/lib/processors/config/index.js +2 -2
- package/dist/lib/processors/config/{mimeTypes.js → mimeConstants.js} +1 -1
- package/dist/lib/processors/index.js +8 -0
- package/dist/lib/providers/googleAiStudio.js +28 -7
- package/dist/lib/providers/googleNativeGemini3.d.ts +18 -0
- package/dist/lib/providers/googleNativeGemini3.js +69 -3
- package/dist/lib/providers/googleVertex.js +33 -9
- package/dist/lib/types/agentNetwork.d.ts +1184 -0
- package/dist/lib/types/agentNetwork.js +8 -0
- package/dist/lib/types/cli.d.ts +66 -0
- package/dist/lib/types/common.d.ts +3 -0
- package/dist/lib/types/generate.d.ts +53 -0
- package/dist/lib/types/index.d.ts +2 -0
- package/dist/lib/types/index.js +3 -0
- package/dist/lib/types/ioProcessor.d.ts +119 -0
- package/dist/lib/types/ioProcessor.js +10 -0
- package/dist/lib/types/providers.d.ts +8 -0
- package/dist/lib/types/stream.d.ts +36 -0
- package/dist/lib/utils/piiDetector.d.ts +24 -0
- package/dist/lib/utils/piiDetector.js +221 -0
- package/dist/lib/utils/pricing.js +144 -26
- package/dist/lib/utils/responseValidator.d.ts +21 -0
- package/dist/lib/utils/responseValidator.js +354 -0
- package/dist/lib/utils/tokenUtils.d.ts +11 -0
- package/dist/lib/utils/tokenUtils.js +33 -2
- package/dist/lib/utils/tripwireEvaluator.d.ts +73 -0
- package/dist/lib/utils/tripwireEvaluator.js +285 -0
- package/dist/neurolink.d.ts +129 -0
- package/dist/neurolink.js +276 -0
- package/dist/processors/config/index.d.ts +2 -2
- package/dist/processors/config/index.js +2 -2
- package/dist/processors/index.js +8 -0
- package/dist/providers/googleAiStudio.js +28 -7
- package/dist/providers/googleNativeGemini3.d.ts +18 -0
- package/dist/providers/googleNativeGemini3.js +69 -3
- package/dist/providers/googleVertex.js +33 -9
- package/dist/types/agentNetwork.d.ts +1184 -0
- package/dist/types/agentNetwork.js +7 -0
- package/dist/types/cli.d.ts +66 -0
- package/dist/types/common.d.ts +3 -0
- package/dist/types/generate.d.ts +53 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.js +3 -0
- package/dist/types/ioProcessor.d.ts +119 -0
- package/dist/types/ioProcessor.js +9 -0
- package/dist/types/providers.d.ts +8 -0
- package/dist/types/stream.d.ts +36 -0
- package/dist/utils/piiDetector.d.ts +24 -0
- package/dist/utils/piiDetector.js +220 -0
- package/dist/utils/pricing.js +144 -26
- package/dist/utils/responseValidator.d.ts +21 -0
- package/dist/utils/responseValidator.js +353 -0
- package/dist/utils/tokenUtils.d.ts +11 -0
- package/dist/utils/tokenUtils.js +33 -2
- package/dist/utils/tripwireEvaluator.d.ts +73 -0
- package/dist/utils/tripwireEvaluator.js +284 -0
- package/package.json +1 -1
- /package/dist/lib/processors/config/{fileTypes.d.ts → fileExtensions.d.ts} +0 -0
- /package/dist/lib/processors/config/{mimeTypes.d.ts → mimeConstants.d.ts} +0 -0
- /package/dist/processors/config/{fileTypes.d.ts → fileExtensions.d.ts} +0 -0
- /package/dist/processors/config/{fileTypes.js → fileExtensions.js} +0 -0
- /package/dist/processors/config/{mimeTypes.d.ts → mimeConstants.d.ts} +0 -0
- /package/dist/processors/config/{mimeTypes.js → mimeConstants.js} +0 -0
|
@@ -0,0 +1,459 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AgentNetwork - Multi-Agent Orchestration for NeuroLink
|
|
3
|
+
*
|
|
4
|
+
* Uses the ai SDK's built-in tool loop: each agent is wrapped as an ai SDK
|
|
5
|
+
* tool, and the network's router is a single neurolink.generate() call with
|
|
6
|
+
* maxSteps. The SDK iterates automatically (tool call → execute → feed result
|
|
7
|
+
* → next call) until the model stops or maxSteps is reached.
|
|
8
|
+
*/
|
|
9
|
+
import { randomUUID } from "crypto";
|
|
10
|
+
import { EventEmitter } from "events";
|
|
11
|
+
import { tool } from "../utils/tool.js";
|
|
12
|
+
import { z } from "zod";
|
|
13
|
+
import { logger } from "../utils/logger.js";
|
|
14
|
+
import { ErrorFactory } from "../utils/errorHandling.js";
|
|
15
|
+
import { Agent } from "./agent.js";
|
|
16
|
+
/**
|
|
17
|
+
* AgentNetwork - Multi-agent orchestration using the ai SDK tool loop
|
|
18
|
+
*
|
|
19
|
+
* Each agent in the network is registered as an ai SDK `tool()`. A single
|
|
20
|
+
* `neurolink.generate()` call with `maxSteps` acts as the router: the model
|
|
21
|
+
* picks which agent tool(s) to call, the SDK executes them and feeds results
|
|
22
|
+
* back, and the loop continues until the model emits `finishReason: "stop"` or
|
|
23
|
+
* maxSteps is exhausted.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```typescript
|
|
27
|
+
* const network = neurolink.createNetwork({
|
|
28
|
+
* name: 'Content Team',
|
|
29
|
+
* agents: [researchAgent, writerAgent, reviewerAgent],
|
|
30
|
+
* router: { model: 'gpt-4o' }
|
|
31
|
+
* });
|
|
32
|
+
*
|
|
33
|
+
* const result = await network.execute({
|
|
34
|
+
* message: 'Write an article about AI trends'
|
|
35
|
+
* });
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export class AgentNetwork {
|
|
39
|
+
id;
|
|
40
|
+
name;
|
|
41
|
+
description;
|
|
42
|
+
neurolink;
|
|
43
|
+
agents = new Map();
|
|
44
|
+
workflows = new Map();
|
|
45
|
+
primitives = new Map();
|
|
46
|
+
emitter;
|
|
47
|
+
config;
|
|
48
|
+
// Lazy tool initialization
|
|
49
|
+
toolsInitialized = false;
|
|
50
|
+
toolsInitPromise = null;
|
|
51
|
+
constructor(config, neurolink) {
|
|
52
|
+
if (!config.name || typeof config.name !== "string") {
|
|
53
|
+
throw ErrorFactory.invalidConfiguration("name", "AgentNetwork config must have a valid name");
|
|
54
|
+
}
|
|
55
|
+
if (!Array.isArray(config.agents) || config.agents.length === 0) {
|
|
56
|
+
throw ErrorFactory.invalidConfiguration("agents", "AgentNetwork config must have at least one agent");
|
|
57
|
+
}
|
|
58
|
+
this.id = config.id ?? randomUUID();
|
|
59
|
+
this.name = config.name;
|
|
60
|
+
this.description = config.description;
|
|
61
|
+
this.neurolink = neurolink;
|
|
62
|
+
this.config = config;
|
|
63
|
+
this.emitter = new EventEmitter();
|
|
64
|
+
this.initializeAgents(config);
|
|
65
|
+
this.initializeWorkflows(config);
|
|
66
|
+
logger.info(`[AgentNetwork:${this.id}] Created network: ${this.name}`, {
|
|
67
|
+
agentCount: this.agents.size,
|
|
68
|
+
workflowCount: this.workflows.size,
|
|
69
|
+
toolCount: config.tools?.length || 0,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
// ============================================================================
|
|
73
|
+
// INITIALIZATION
|
|
74
|
+
// ============================================================================
|
|
75
|
+
initializeAgents(config) {
|
|
76
|
+
for (const agentDef of config.agents) {
|
|
77
|
+
const agent = new Agent(agentDef, this.neurolink);
|
|
78
|
+
this.agents.set(agentDef.id, agent);
|
|
79
|
+
const primitive = {
|
|
80
|
+
id: agentDef.id,
|
|
81
|
+
type: "agent",
|
|
82
|
+
name: agentDef.name,
|
|
83
|
+
description: agentDef.description,
|
|
84
|
+
inputSchema: agentDef.inputSchema,
|
|
85
|
+
outputSchema: agentDef.outputSchema,
|
|
86
|
+
agent,
|
|
87
|
+
};
|
|
88
|
+
this.primitives.set(agentDef.id, primitive);
|
|
89
|
+
logger.debug(`[AgentNetwork:${this.id}] Registered agent: ${agentDef.name}`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
initializeWorkflows(config) {
|
|
93
|
+
if (!config.workflows) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
for (const workflowDef of config.workflows) {
|
|
97
|
+
const primitive = {
|
|
98
|
+
id: workflowDef.id,
|
|
99
|
+
type: "workflow",
|
|
100
|
+
name: workflowDef.name,
|
|
101
|
+
description: workflowDef.description,
|
|
102
|
+
inputSchema: workflowDef.inputSchema,
|
|
103
|
+
outputSchema: workflowDef.outputSchema,
|
|
104
|
+
workflow: workflowDef.workflow,
|
|
105
|
+
};
|
|
106
|
+
this.workflows.set(workflowDef.id, primitive);
|
|
107
|
+
this.primitives.set(workflowDef.id, primitive);
|
|
108
|
+
logger.debug(`[AgentNetwork:${this.id}] Registered workflow: ${workflowDef.name}`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
async initializeTools() {
|
|
112
|
+
if (!this.config.tools || this.config.tools.length === 0) {
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
try {
|
|
116
|
+
const availableTools = await this.neurolink.getAllAvailableTools();
|
|
117
|
+
for (const toolName of this.config.tools) {
|
|
118
|
+
if (this.primitives.has(`tool-${toolName}`)) {
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
const toolInfo = availableTools.find((t) => t.name === toolName);
|
|
122
|
+
if (!toolInfo) {
|
|
123
|
+
logger.warn(`[AgentNetwork:${this.id}] Tool not found: ${toolName}`);
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
const primitive = {
|
|
127
|
+
id: `tool-${toolName}`,
|
|
128
|
+
type: "tool",
|
|
129
|
+
name: toolName,
|
|
130
|
+
description: toolInfo.description || `Tool: ${toolName}`,
|
|
131
|
+
tool: {
|
|
132
|
+
name: toolName,
|
|
133
|
+
description: toolInfo.description,
|
|
134
|
+
inputSchema: toolInfo.inputSchema,
|
|
135
|
+
},
|
|
136
|
+
execute: async (args) => {
|
|
137
|
+
return this.neurolink.executeTool(toolName, args);
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
this.primitives.set(primitive.id, primitive);
|
|
141
|
+
logger.debug(`[AgentNetwork:${this.id}] Registered tool: ${toolName}`);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
catch (error) {
|
|
145
|
+
logger.warn(`[AgentNetwork:${this.id}] Failed to initialize tools`, {
|
|
146
|
+
error: error instanceof Error ? error.message : String(error),
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
async ensureToolsInitialized() {
|
|
151
|
+
if (this.toolsInitialized) {
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
if (this.toolsInitPromise) {
|
|
155
|
+
return this.toolsInitPromise;
|
|
156
|
+
}
|
|
157
|
+
this.toolsInitPromise = this.initializeTools();
|
|
158
|
+
await this.toolsInitPromise;
|
|
159
|
+
this.toolsInitialized = true;
|
|
160
|
+
}
|
|
161
|
+
// ============================================================================
|
|
162
|
+
// AGENT-AS-TOOL CONSTRUCTION
|
|
163
|
+
// ============================================================================
|
|
164
|
+
/**
|
|
165
|
+
* Build a Record of ai SDK tools — one per agent in the network.
|
|
166
|
+
* The router model calls these tools to delegate subtasks.
|
|
167
|
+
*/
|
|
168
|
+
buildAgentTools() {
|
|
169
|
+
const tools = {};
|
|
170
|
+
for (const [id, agentInstance] of this.agents) {
|
|
171
|
+
// Capture in closure so the async execute below closes over the right values
|
|
172
|
+
const capturedId = id;
|
|
173
|
+
const capturedAgent = agentInstance;
|
|
174
|
+
const schema = z.object({
|
|
175
|
+
task: z.string().describe("The task to delegate to this agent"),
|
|
176
|
+
});
|
|
177
|
+
tools[`agent_${capturedId}`] = tool({
|
|
178
|
+
description: `Agent: ${capturedAgent.name} - ${capturedAgent.description}`,
|
|
179
|
+
inputSchema: schema,
|
|
180
|
+
execute: async (params) => {
|
|
181
|
+
logger.debug(`[AgentNetwork:${this.id}] Delegating to agent: ${capturedAgent.name}`, { task: params.task.slice(0, 100) });
|
|
182
|
+
const result = await capturedAgent.execute(params.task);
|
|
183
|
+
return {
|
|
184
|
+
agentId: capturedId,
|
|
185
|
+
content: result.content,
|
|
186
|
+
status: result.status,
|
|
187
|
+
error: result.error,
|
|
188
|
+
};
|
|
189
|
+
},
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
return tools;
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Build the router system prompt that describes all available agents and
|
|
196
|
+
* instructs the model to delegate tasks via agent tools.
|
|
197
|
+
*/
|
|
198
|
+
buildRouterSystemPrompt() {
|
|
199
|
+
const agentDescriptions = Array.from(this.agents.values())
|
|
200
|
+
.map((a) => `- agent_${a.id}: ${a.name} — ${a.description}`)
|
|
201
|
+
.join("\n");
|
|
202
|
+
const baseInstructions = this.config.router?.instructions ??
|
|
203
|
+
"You are a task orchestrator. Analyze the user's request and delegate to the most appropriate agent(s). You may call multiple agents sequentially if the task requires multiple steps. Once all necessary agents have responded, synthesize their outputs into a final answer.";
|
|
204
|
+
return `${baseInstructions}
|
|
205
|
+
|
|
206
|
+
Available agents:
|
|
207
|
+
${agentDescriptions}
|
|
208
|
+
|
|
209
|
+
Use the appropriate agent tool(s) to handle the task. Return a clear, complete final answer once all needed agents have completed their work.`;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Build NetworkExecutionTrace steps from generate() toolExecutions.
|
|
213
|
+
*/
|
|
214
|
+
buildTrace(toolExecutions, traceId, startTime) {
|
|
215
|
+
const steps = (toolExecutions ?? []).map((exec, index) => {
|
|
216
|
+
// Tool name format is "agent_<id>" — extract agent id
|
|
217
|
+
const agentId = exec.name.startsWith("agent_")
|
|
218
|
+
? exec.name.slice("agent_".length)
|
|
219
|
+
: exec.name;
|
|
220
|
+
const primitive = this.primitives.get(agentId);
|
|
221
|
+
return {
|
|
222
|
+
index,
|
|
223
|
+
primitive: {
|
|
224
|
+
type: primitive?.type ?? "agent",
|
|
225
|
+
id: agentId,
|
|
226
|
+
name: primitive?.name ?? agentId,
|
|
227
|
+
},
|
|
228
|
+
input: exec.input,
|
|
229
|
+
output: exec.output,
|
|
230
|
+
duration: 0, // individual step timing not available from generate()
|
|
231
|
+
timestamp: startTime,
|
|
232
|
+
};
|
|
233
|
+
});
|
|
234
|
+
return {
|
|
235
|
+
traceId,
|
|
236
|
+
steps,
|
|
237
|
+
routingDecisions: [], // routing is implicit in the model's tool calls
|
|
238
|
+
startTime,
|
|
239
|
+
endTime: Date.now(),
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
// ============================================================================
|
|
243
|
+
// PUBLIC EXECUTION API
|
|
244
|
+
// ============================================================================
|
|
245
|
+
/**
|
|
246
|
+
* Execute the network with intelligent routing via the ai SDK tool loop.
|
|
247
|
+
*
|
|
248
|
+
* A single `neurolink.generate()` call is issued. The model decides which
|
|
249
|
+
* agent tool(s) to call; the SDK executes them and loops until `stop` or
|
|
250
|
+
* `maxSteps` is reached.
|
|
251
|
+
*/
|
|
252
|
+
async execute(input, options) {
|
|
253
|
+
const startTime = Date.now();
|
|
254
|
+
const traceId = options?.tracing?.traceId ?? randomUUID();
|
|
255
|
+
const maxSteps = options?.maxSteps ?? this.config.defaults?.maxSteps ?? 10;
|
|
256
|
+
await this.ensureToolsInitialized();
|
|
257
|
+
const message = this.extractMessageContent(input.message);
|
|
258
|
+
logger.info(`[AgentNetwork:${this.id}] Starting execute`, {
|
|
259
|
+
traceId,
|
|
260
|
+
maxSteps,
|
|
261
|
+
agentCount: this.agents.size,
|
|
262
|
+
});
|
|
263
|
+
this.emit("network:start", { traceId, input: message, startTime });
|
|
264
|
+
try {
|
|
265
|
+
const agentTools = this.buildAgentTools();
|
|
266
|
+
const systemPrompt = this.buildRouterSystemPrompt();
|
|
267
|
+
const result = await this.neurolink.generate({
|
|
268
|
+
input: { text: message },
|
|
269
|
+
systemPrompt,
|
|
270
|
+
provider: this.config.router?.provider,
|
|
271
|
+
model: this.config.router?.model,
|
|
272
|
+
maxSteps,
|
|
273
|
+
tools: agentTools,
|
|
274
|
+
});
|
|
275
|
+
const toolExecutions = (result.toolExecutions ?? []);
|
|
276
|
+
const trace = this.buildTrace(toolExecutions, traceId, startTime);
|
|
277
|
+
// Aggregate token usage across all agent tool calls
|
|
278
|
+
const usage = result.usage;
|
|
279
|
+
const totalUsage = {
|
|
280
|
+
promptTokens: usage?.input ?? 0,
|
|
281
|
+
completionTokens: usage?.output ?? 0,
|
|
282
|
+
totalTokens: usage?.total ?? 0,
|
|
283
|
+
byAgent: {},
|
|
284
|
+
};
|
|
285
|
+
const executionResult = {
|
|
286
|
+
content: result.content || "",
|
|
287
|
+
trace,
|
|
288
|
+
usage: totalUsage,
|
|
289
|
+
status: "completed",
|
|
290
|
+
duration: Date.now() - startTime,
|
|
291
|
+
};
|
|
292
|
+
this.emit("network:complete", { traceId, result: executionResult });
|
|
293
|
+
return executionResult;
|
|
294
|
+
}
|
|
295
|
+
catch (error) {
|
|
296
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
297
|
+
logger.error(`[AgentNetwork:${this.id}] Execution failed`, {
|
|
298
|
+
traceId,
|
|
299
|
+
error: errorMessage,
|
|
300
|
+
});
|
|
301
|
+
const failedResult = {
|
|
302
|
+
content: "",
|
|
303
|
+
trace: {
|
|
304
|
+
traceId,
|
|
305
|
+
steps: [],
|
|
306
|
+
routingDecisions: [],
|
|
307
|
+
startTime,
|
|
308
|
+
endTime: Date.now(),
|
|
309
|
+
},
|
|
310
|
+
usage: { promptTokens: 0, completionTokens: 0, totalTokens: 0 },
|
|
311
|
+
status: "error",
|
|
312
|
+
duration: Date.now() - startTime,
|
|
313
|
+
error: errorMessage,
|
|
314
|
+
};
|
|
315
|
+
this.emit("network:error", { traceId, error: errorMessage });
|
|
316
|
+
return failedResult;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Stream network execution using the ai SDK tool loop.
|
|
321
|
+
*
|
|
322
|
+
* Calls `neurolink.stream()` with agent tools. Text chunks, tool calls, and
|
|
323
|
+
* tool results are forwarded as typed NetworkStreamChunk events.
|
|
324
|
+
*/
|
|
325
|
+
async *stream(input, options) {
|
|
326
|
+
const startTime = Date.now();
|
|
327
|
+
const traceId = options?.tracing?.traceId ?? randomUUID();
|
|
328
|
+
const maxSteps = options?.maxSteps ?? this.config.defaults?.maxSteps ?? 10;
|
|
329
|
+
await this.ensureToolsInitialized();
|
|
330
|
+
const message = this.extractMessageContent(input.message);
|
|
331
|
+
yield {
|
|
332
|
+
type: "network-start",
|
|
333
|
+
networkId: this.id,
|
|
334
|
+
input: message,
|
|
335
|
+
timestamp: startTime,
|
|
336
|
+
traceId,
|
|
337
|
+
};
|
|
338
|
+
const totalUsage = {
|
|
339
|
+
promptTokens: 0,
|
|
340
|
+
completionTokens: 0,
|
|
341
|
+
totalTokens: 0,
|
|
342
|
+
};
|
|
343
|
+
let finalContent = "";
|
|
344
|
+
try {
|
|
345
|
+
const agentTools = this.buildAgentTools();
|
|
346
|
+
const systemPrompt = this.buildRouterSystemPrompt();
|
|
347
|
+
const streamResult = await this.neurolink.stream({
|
|
348
|
+
input: { text: message },
|
|
349
|
+
systemPrompt,
|
|
350
|
+
provider: this.config.router?.provider,
|
|
351
|
+
model: this.config.router?.model,
|
|
352
|
+
maxSteps,
|
|
353
|
+
tools: agentTools,
|
|
354
|
+
});
|
|
355
|
+
for await (const chunk of streamResult.stream) {
|
|
356
|
+
if ("content" in chunk && typeof chunk.content === "string") {
|
|
357
|
+
finalContent += chunk.content;
|
|
358
|
+
yield {
|
|
359
|
+
type: "agent-text",
|
|
360
|
+
agentId: this.id,
|
|
361
|
+
content: chunk.content,
|
|
362
|
+
isPartial: true,
|
|
363
|
+
timestamp: Date.now(),
|
|
364
|
+
traceId,
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
else if ("toolCall" in chunk) {
|
|
368
|
+
const tc = chunk;
|
|
369
|
+
yield {
|
|
370
|
+
type: "agent-tool-call",
|
|
371
|
+
agentId: this.id,
|
|
372
|
+
toolName: tc.toolCall?.toolName ?? "unknown",
|
|
373
|
+
args: tc.toolCall?.args,
|
|
374
|
+
toolCallId: tc.toolCall?.toolCallId ?? `tool-${Date.now()}`,
|
|
375
|
+
timestamp: Date.now(),
|
|
376
|
+
traceId,
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
else if ("toolResult" in chunk) {
|
|
380
|
+
const tr = chunk;
|
|
381
|
+
yield {
|
|
382
|
+
type: "agent-tool-result",
|
|
383
|
+
agentId: this.id,
|
|
384
|
+
toolName: tr.toolResult?.toolName ?? "unknown",
|
|
385
|
+
toolCallId: tr.toolResult?.toolCallId ?? `tool-${Date.now()}`,
|
|
386
|
+
result: tr.toolResult?.result,
|
|
387
|
+
success: true,
|
|
388
|
+
timestamp: Date.now(),
|
|
389
|
+
traceId,
|
|
390
|
+
};
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
// Collect final usage if available
|
|
394
|
+
if (streamResult.usage) {
|
|
395
|
+
totalUsage.promptTokens = streamResult.usage.input ?? 0;
|
|
396
|
+
totalUsage.completionTokens = streamResult.usage.output ?? 0;
|
|
397
|
+
totalUsage.totalTokens = streamResult.usage.total ?? 0;
|
|
398
|
+
}
|
|
399
|
+
const trace = {
|
|
400
|
+
traceId,
|
|
401
|
+
steps: [],
|
|
402
|
+
routingDecisions: [],
|
|
403
|
+
startTime,
|
|
404
|
+
endTime: Date.now(),
|
|
405
|
+
};
|
|
406
|
+
yield {
|
|
407
|
+
type: "network-complete",
|
|
408
|
+
result: {
|
|
409
|
+
content: finalContent,
|
|
410
|
+
trace,
|
|
411
|
+
usage: totalUsage,
|
|
412
|
+
status: "completed",
|
|
413
|
+
duration: Date.now() - startTime,
|
|
414
|
+
},
|
|
415
|
+
timestamp: Date.now(),
|
|
416
|
+
traceId,
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
catch (error) {
|
|
420
|
+
yield {
|
|
421
|
+
type: "network-error",
|
|
422
|
+
error: error instanceof Error ? error.message : String(error),
|
|
423
|
+
timestamp: Date.now(),
|
|
424
|
+
traceId,
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
// ============================================================================
|
|
429
|
+
// PUBLIC ACCESSORS
|
|
430
|
+
// ============================================================================
|
|
431
|
+
getAgent(id) {
|
|
432
|
+
return this.agents.get(id);
|
|
433
|
+
}
|
|
434
|
+
getAllAgents() {
|
|
435
|
+
return Array.from(this.agents.values());
|
|
436
|
+
}
|
|
437
|
+
getAllPrimitives() {
|
|
438
|
+
return Array.from(this.primitives.values());
|
|
439
|
+
}
|
|
440
|
+
on(event, handler) {
|
|
441
|
+
this.emitter.on(event, handler);
|
|
442
|
+
}
|
|
443
|
+
off(event, handler) {
|
|
444
|
+
this.emitter.off(event, handler);
|
|
445
|
+
}
|
|
446
|
+
// ============================================================================
|
|
447
|
+
// PRIVATE HELPERS
|
|
448
|
+
// ============================================================================
|
|
449
|
+
extractMessageContent(message) {
|
|
450
|
+
if (typeof message === "string") {
|
|
451
|
+
return message;
|
|
452
|
+
}
|
|
453
|
+
return message.map((m) => m.content).join("\n");
|
|
454
|
+
}
|
|
455
|
+
emit(event, ...args) {
|
|
456
|
+
this.emitter.emit(event, ...args);
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
//# sourceMappingURL=agentNetwork.js.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Communication Module
|
|
3
|
+
*
|
|
4
|
+
* Provides communication infrastructure for multi-agent networks.
|
|
5
|
+
*
|
|
6
|
+
* Types for this module live in src/lib/types/agentNetwork.ts and are
|
|
7
|
+
* re-exported via the central barrel at src/lib/types/index.ts.
|
|
8
|
+
*/
|
|
9
|
+
export { MessageBus } from "./message-bus.js";
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Communication Module
|
|
3
|
+
*
|
|
4
|
+
* Provides communication infrastructure for multi-agent networks.
|
|
5
|
+
*
|
|
6
|
+
* Types for this module live in src/lib/types/agentNetwork.ts and are
|
|
7
|
+
* re-exported via the central barrel at src/lib/types/index.ts.
|
|
8
|
+
*/
|
|
9
|
+
export { MessageBus } from "./message-bus.js";
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Message Bus - Inter-agent communication infrastructure
|
|
3
|
+
*
|
|
4
|
+
* Provides a publish-subscribe message bus for agent-to-agent communication
|
|
5
|
+
* with support for:
|
|
6
|
+
* - Topic-based messaging
|
|
7
|
+
* - Request-response patterns
|
|
8
|
+
* - Broadcast messaging
|
|
9
|
+
* - Message persistence and replay
|
|
10
|
+
*/
|
|
11
|
+
import type { AgentMessage, MessageHandler, SubscriptionOptions, MessageBusConfig } from "../../types/index.js";
|
|
12
|
+
/**
|
|
13
|
+
* Message Bus - Central hub for agent communication
|
|
14
|
+
*/
|
|
15
|
+
export declare class MessageBus {
|
|
16
|
+
private subscriptions;
|
|
17
|
+
private messageHistory;
|
|
18
|
+
private pendingRequests;
|
|
19
|
+
private deadLetterQueue;
|
|
20
|
+
private config;
|
|
21
|
+
private emitter;
|
|
22
|
+
constructor(config?: MessageBusConfig);
|
|
23
|
+
/**
|
|
24
|
+
* Subscribe to a topic
|
|
25
|
+
*/
|
|
26
|
+
subscribe(topic: string, subscriberId: string, handler: MessageHandler, options?: SubscriptionOptions): string;
|
|
27
|
+
/**
|
|
28
|
+
* Unsubscribe from a topic
|
|
29
|
+
*/
|
|
30
|
+
unsubscribe(subscriptionId: string): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Unsubscribe all subscriptions for an agent
|
|
33
|
+
*/
|
|
34
|
+
unsubscribeAll(subscriberId: string): number;
|
|
35
|
+
/**
|
|
36
|
+
* Publish a message to a topic
|
|
37
|
+
*/
|
|
38
|
+
publish(topic: string, senderId: string, payload: unknown, options?: Partial<Omit<AgentMessage, "id" | "topic" | "senderId" | "payload" | "timestamp">>): Promise<void>;
|
|
39
|
+
/**
|
|
40
|
+
* Send a direct message to a specific agent
|
|
41
|
+
*/
|
|
42
|
+
sendDirect(senderId: string, recipientId: string, payload: unknown, options?: Partial<Omit<AgentMessage, "id" | "senderId" | "recipientId" | "payload" | "timestamp">>): Promise<void>;
|
|
43
|
+
/**
|
|
44
|
+
* Send a request and wait for response
|
|
45
|
+
*/
|
|
46
|
+
request(topic: string, senderId: string, payload: unknown, timeout?: number): Promise<AgentMessage>;
|
|
47
|
+
/**
|
|
48
|
+
* Reply to a request
|
|
49
|
+
*/
|
|
50
|
+
reply(originalMessage: AgentMessage, senderId: string, payload: unknown): Promise<void>;
|
|
51
|
+
/**
|
|
52
|
+
* Broadcast a message to all subscribers
|
|
53
|
+
*/
|
|
54
|
+
broadcast(senderId: string, payload: unknown, excludeTopics?: string[]): Promise<void>;
|
|
55
|
+
/**
|
|
56
|
+
* Deliver a message to subscribers
|
|
57
|
+
*/
|
|
58
|
+
private deliverMessage;
|
|
59
|
+
/**
|
|
60
|
+
* Check if message should be delivered to subscription
|
|
61
|
+
*/
|
|
62
|
+
private shouldDeliver;
|
|
63
|
+
/**
|
|
64
|
+
* Unsubscribe by topic for a specific subscriber
|
|
65
|
+
*/
|
|
66
|
+
private unsubscribeByTopic;
|
|
67
|
+
/**
|
|
68
|
+
* Get message history for a topic
|
|
69
|
+
*/
|
|
70
|
+
getHistory(topic?: string, limit?: number): AgentMessage[];
|
|
71
|
+
/**
|
|
72
|
+
* Get dead letter queue messages
|
|
73
|
+
*/
|
|
74
|
+
getDeadLetterQueue(): AgentMessage[];
|
|
75
|
+
/**
|
|
76
|
+
* Clear dead letter queue
|
|
77
|
+
*/
|
|
78
|
+
clearDeadLetterQueue(): void;
|
|
79
|
+
/**
|
|
80
|
+
* Replay messages from history
|
|
81
|
+
*/
|
|
82
|
+
replayHistory(topic: string, subscriberId: string, since?: number): Promise<void>;
|
|
83
|
+
/**
|
|
84
|
+
* Get all topics
|
|
85
|
+
*/
|
|
86
|
+
getTopics(): string[];
|
|
87
|
+
/**
|
|
88
|
+
* Get subscriber count for a topic
|
|
89
|
+
*/
|
|
90
|
+
getSubscriberCount(topic: string): number;
|
|
91
|
+
/**
|
|
92
|
+
* Get statistics
|
|
93
|
+
*/
|
|
94
|
+
getStats(): {
|
|
95
|
+
topicCount: number;
|
|
96
|
+
totalSubscriptions: number;
|
|
97
|
+
historySize: number;
|
|
98
|
+
deadLetterQueueSize: number;
|
|
99
|
+
pendingRequests: number;
|
|
100
|
+
};
|
|
101
|
+
/**
|
|
102
|
+
* Subscribe to bus events
|
|
103
|
+
*/
|
|
104
|
+
on(event: string, handler: (...args: unknown[]) => void): void;
|
|
105
|
+
/**
|
|
106
|
+
* Unsubscribe from bus events
|
|
107
|
+
*/
|
|
108
|
+
off(event: string, handler: (...args: unknown[]) => void): void;
|
|
109
|
+
/**
|
|
110
|
+
* Shutdown the message bus
|
|
111
|
+
*/
|
|
112
|
+
shutdown(): void;
|
|
113
|
+
}
|