@juspay/neurolink 9.83.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 +12 -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 +3 -3
- package/dist/lib/providers/googleNativeGemini3.d.ts +18 -0
- package/dist/lib/providers/googleNativeGemini3.js +47 -1
- package/dist/lib/providers/googleVertex.js +5 -5
- 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/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/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/responseValidator.d.ts +21 -0
- package/dist/lib/utils/responseValidator.js +354 -0
- 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 +3 -3
- package/dist/providers/googleNativeGemini3.d.ts +18 -0
- package/dist/providers/googleNativeGemini3.js +47 -1
- package/dist/providers/googleVertex.js +5 -5
- 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/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/stream.d.ts +36 -0
- package/dist/utils/piiDetector.d.ts +24 -0
- package/dist/utils/piiDetector.js +220 -0
- package/dist/utils/responseValidator.d.ts +21 -0
- package/dist/utils/responseValidator.js +353 -0
- 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,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Network Topology - Defines and manages network structure
|
|
3
|
+
*
|
|
4
|
+
* Provides different topology patterns for agent networks:
|
|
5
|
+
* - Star: Central coordinator with peripheral agents
|
|
6
|
+
* - Mesh: All agents can communicate with each other
|
|
7
|
+
* - Hierarchical: Tree structure with supervisors and workers
|
|
8
|
+
* - Ring: Agents form a circular communication pattern
|
|
9
|
+
* - Custom: User-defined topology
|
|
10
|
+
*/
|
|
11
|
+
import type { Agent } from "../agent.js";
|
|
12
|
+
import type { TopologyType, TopologyNode, TopologyEdge, TopologyConfig, TopologyStats } from "../../types/index.js";
|
|
13
|
+
/**
|
|
14
|
+
* Network Topology - Manages agent network structure
|
|
15
|
+
*/
|
|
16
|
+
export declare class NetworkTopology {
|
|
17
|
+
private nodes;
|
|
18
|
+
private edges;
|
|
19
|
+
private config;
|
|
20
|
+
private topologyId;
|
|
21
|
+
constructor(config: TopologyConfig);
|
|
22
|
+
/**
|
|
23
|
+
* Build topology from agents
|
|
24
|
+
*/
|
|
25
|
+
buildFromAgents(agents: Agent[]): void;
|
|
26
|
+
/**
|
|
27
|
+
* Add a node to the topology
|
|
28
|
+
*/
|
|
29
|
+
addNode(agent: Agent, role?: TopologyNode["role"]): TopologyNode;
|
|
30
|
+
/**
|
|
31
|
+
* Remove a node from the topology
|
|
32
|
+
*/
|
|
33
|
+
removeNode(nodeId: string): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Add an edge between nodes
|
|
36
|
+
*/
|
|
37
|
+
addEdge(sourceId: string, targetId: string, type?: TopologyEdge["type"], weight?: number): TopologyEdge | undefined;
|
|
38
|
+
/**
|
|
39
|
+
* Remove an edge
|
|
40
|
+
*/
|
|
41
|
+
removeEdge(edgeId: string): boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Build star topology (hub and spoke)
|
|
44
|
+
*/
|
|
45
|
+
private buildStarTopology;
|
|
46
|
+
/**
|
|
47
|
+
* Build mesh topology (fully connected)
|
|
48
|
+
*/
|
|
49
|
+
private buildMeshTopology;
|
|
50
|
+
/**
|
|
51
|
+
* Build hierarchical topology (tree)
|
|
52
|
+
*/
|
|
53
|
+
private buildHierarchicalTopology;
|
|
54
|
+
/**
|
|
55
|
+
* Build ring topology
|
|
56
|
+
*/
|
|
57
|
+
private buildRingTopology;
|
|
58
|
+
/**
|
|
59
|
+
* Build custom topology from configuration
|
|
60
|
+
*/
|
|
61
|
+
private buildCustomTopology;
|
|
62
|
+
/**
|
|
63
|
+
* Get node by ID
|
|
64
|
+
*/
|
|
65
|
+
getNode(nodeId: string): TopologyNode | undefined;
|
|
66
|
+
/**
|
|
67
|
+
* Get node by agent ID
|
|
68
|
+
*/
|
|
69
|
+
getNodeByAgentId(agentId: string): TopologyNode | undefined;
|
|
70
|
+
/**
|
|
71
|
+
* Get all nodes
|
|
72
|
+
*/
|
|
73
|
+
getAllNodes(): TopologyNode[];
|
|
74
|
+
/**
|
|
75
|
+
* Get all edges
|
|
76
|
+
*/
|
|
77
|
+
getAllEdges(): TopologyEdge[];
|
|
78
|
+
/**
|
|
79
|
+
* Get connected nodes
|
|
80
|
+
*/
|
|
81
|
+
getConnectedNodes(nodeId: string): TopologyNode[];
|
|
82
|
+
/**
|
|
83
|
+
* Find shortest path between two nodes (BFS)
|
|
84
|
+
*/
|
|
85
|
+
findShortestPath(sourceId: string, targetId: string): string[] | undefined;
|
|
86
|
+
/**
|
|
87
|
+
* Check if two nodes are connected (directly or indirectly)
|
|
88
|
+
*/
|
|
89
|
+
areConnected(sourceId: string, targetId: string): boolean;
|
|
90
|
+
/**
|
|
91
|
+
* Get nodes by role
|
|
92
|
+
*/
|
|
93
|
+
getNodesByRole(role: TopologyNode["role"]): TopologyNode[];
|
|
94
|
+
/**
|
|
95
|
+
* Get coordinator/root node
|
|
96
|
+
*/
|
|
97
|
+
getCoordinator(): TopologyNode | undefined;
|
|
98
|
+
/**
|
|
99
|
+
* Calculate topology statistics
|
|
100
|
+
*/
|
|
101
|
+
getStats(): TopologyStats;
|
|
102
|
+
/**
|
|
103
|
+
* Export topology as JSON
|
|
104
|
+
*/
|
|
105
|
+
toJSON(): {
|
|
106
|
+
id: string;
|
|
107
|
+
type: TopologyType;
|
|
108
|
+
nodes: TopologyNode[];
|
|
109
|
+
edges: TopologyEdge[];
|
|
110
|
+
};
|
|
111
|
+
/**
|
|
112
|
+
* Import topology from JSON
|
|
113
|
+
*/
|
|
114
|
+
fromJSON(data: {
|
|
115
|
+
id?: string;
|
|
116
|
+
type: TopologyType;
|
|
117
|
+
nodes: TopologyNode[];
|
|
118
|
+
edges: TopologyEdge[];
|
|
119
|
+
}): void;
|
|
120
|
+
/**
|
|
121
|
+
* Get topology type
|
|
122
|
+
*/
|
|
123
|
+
getType(): TopologyType;
|
|
124
|
+
/**
|
|
125
|
+
* Get topology ID
|
|
126
|
+
*/
|
|
127
|
+
getId(): string;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Topology builder for fluent API
|
|
131
|
+
*/
|
|
132
|
+
export declare class TopologyBuilder {
|
|
133
|
+
private agents;
|
|
134
|
+
private config;
|
|
135
|
+
constructor(type: TopologyType);
|
|
136
|
+
/**
|
|
137
|
+
* Add an agent
|
|
138
|
+
*/
|
|
139
|
+
addAgent(agent: Agent): TopologyBuilder;
|
|
140
|
+
/**
|
|
141
|
+
* Add multiple agents
|
|
142
|
+
*/
|
|
143
|
+
addAgents(agents: Agent[]): TopologyBuilder;
|
|
144
|
+
/**
|
|
145
|
+
* Set coordinator (for star topology)
|
|
146
|
+
*/
|
|
147
|
+
setCoordinator(agentId: string): TopologyBuilder;
|
|
148
|
+
/**
|
|
149
|
+
* Set root (for hierarchical topology)
|
|
150
|
+
*/
|
|
151
|
+
setRoot(agentId: string): TopologyBuilder;
|
|
152
|
+
/**
|
|
153
|
+
* Set max children (for hierarchical topology)
|
|
154
|
+
*/
|
|
155
|
+
setMaxChildren(max: number): TopologyBuilder;
|
|
156
|
+
/**
|
|
157
|
+
* Add custom edge
|
|
158
|
+
*/
|
|
159
|
+
addCustomEdge(sourceAgentId: string, targetAgentId: string, bidirectional?: boolean): TopologyBuilder;
|
|
160
|
+
/**
|
|
161
|
+
* Build the topology
|
|
162
|
+
*/
|
|
163
|
+
build(): NetworkTopology;
|
|
164
|
+
}
|
|
@@ -0,0 +1,521 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Network Topology - Defines and manages network structure
|
|
3
|
+
*
|
|
4
|
+
* Provides different topology patterns for agent networks:
|
|
5
|
+
* - Star: Central coordinator with peripheral agents
|
|
6
|
+
* - Mesh: All agents can communicate with each other
|
|
7
|
+
* - Hierarchical: Tree structure with supervisors and workers
|
|
8
|
+
* - Ring: Agents form a circular communication pattern
|
|
9
|
+
* - Custom: User-defined topology
|
|
10
|
+
*/
|
|
11
|
+
import { randomUUID } from "crypto";
|
|
12
|
+
import { logger } from "../../utils/logger.js";
|
|
13
|
+
/**
|
|
14
|
+
* Network Topology - Manages agent network structure
|
|
15
|
+
*/
|
|
16
|
+
export class NetworkTopology {
|
|
17
|
+
nodes = new Map();
|
|
18
|
+
edges = new Map();
|
|
19
|
+
config;
|
|
20
|
+
topologyId;
|
|
21
|
+
constructor(config) {
|
|
22
|
+
this.config = config;
|
|
23
|
+
this.topologyId = randomUUID();
|
|
24
|
+
logger.debug(`[NetworkTopology] Created with type: ${config.type}`);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Build topology from agents
|
|
28
|
+
*/
|
|
29
|
+
buildFromAgents(agents) {
|
|
30
|
+
// Clear existing topology
|
|
31
|
+
this.nodes.clear();
|
|
32
|
+
this.edges.clear();
|
|
33
|
+
// Create nodes for all agents
|
|
34
|
+
for (const agent of agents) {
|
|
35
|
+
this.addNode(agent);
|
|
36
|
+
}
|
|
37
|
+
// Build edges based on topology type
|
|
38
|
+
switch (this.config.type) {
|
|
39
|
+
case "star":
|
|
40
|
+
this.buildStarTopology(agents);
|
|
41
|
+
break;
|
|
42
|
+
case "mesh":
|
|
43
|
+
this.buildMeshTopology(agents);
|
|
44
|
+
break;
|
|
45
|
+
case "hierarchical":
|
|
46
|
+
this.buildHierarchicalTopology(agents);
|
|
47
|
+
break;
|
|
48
|
+
case "ring":
|
|
49
|
+
this.buildRingTopology(agents);
|
|
50
|
+
break;
|
|
51
|
+
case "custom":
|
|
52
|
+
this.buildCustomTopology(agents);
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
logger.info(`[NetworkTopology] Built ${this.config.type} topology`, {
|
|
56
|
+
nodes: this.nodes.size,
|
|
57
|
+
edges: this.edges.size,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Add a node to the topology
|
|
62
|
+
*/
|
|
63
|
+
addNode(agent, role) {
|
|
64
|
+
const node = {
|
|
65
|
+
id: `node-${agent.id}`,
|
|
66
|
+
agentId: agent.id,
|
|
67
|
+
agentName: agent.name,
|
|
68
|
+
role: role ?? "worker",
|
|
69
|
+
connections: [],
|
|
70
|
+
childIds: [],
|
|
71
|
+
};
|
|
72
|
+
this.nodes.set(node.id, node);
|
|
73
|
+
return node;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Remove a node from the topology
|
|
77
|
+
*/
|
|
78
|
+
removeNode(nodeId) {
|
|
79
|
+
const node = this.nodes.get(nodeId);
|
|
80
|
+
if (!node) {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
// Remove all edges connected to this node
|
|
84
|
+
for (const edgeId of [...this.edges.keys()]) {
|
|
85
|
+
const edge = this.edges.get(edgeId);
|
|
86
|
+
if (edge.sourceId === nodeId || edge.targetId === nodeId) {
|
|
87
|
+
this.edges.delete(edgeId);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
// Remove from other nodes' connections
|
|
91
|
+
for (const otherNode of this.nodes.values()) {
|
|
92
|
+
otherNode.connections = otherNode.connections.filter((id) => id !== nodeId);
|
|
93
|
+
otherNode.childIds = otherNode.childIds.filter((id) => id !== nodeId);
|
|
94
|
+
if (otherNode.parentId === nodeId) {
|
|
95
|
+
otherNode.parentId = undefined;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
this.nodes.delete(nodeId);
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Add an edge between nodes
|
|
103
|
+
*/
|
|
104
|
+
addEdge(sourceId, targetId, type = "bidirectional", weight = 1) {
|
|
105
|
+
const sourceNode = this.nodes.get(sourceId);
|
|
106
|
+
const targetNode = this.nodes.get(targetId);
|
|
107
|
+
if (!sourceNode || !targetNode) {
|
|
108
|
+
logger.warn(`[NetworkTopology] Cannot add edge: node not found`);
|
|
109
|
+
return undefined;
|
|
110
|
+
}
|
|
111
|
+
const edge = {
|
|
112
|
+
id: `edge-${sourceId}-${targetId}`,
|
|
113
|
+
sourceId,
|
|
114
|
+
targetId,
|
|
115
|
+
type,
|
|
116
|
+
weight,
|
|
117
|
+
};
|
|
118
|
+
this.edges.set(edge.id, edge);
|
|
119
|
+
// Update node connections
|
|
120
|
+
if (!sourceNode.connections.includes(targetId)) {
|
|
121
|
+
sourceNode.connections.push(targetId);
|
|
122
|
+
}
|
|
123
|
+
if (type === "bidirectional" &&
|
|
124
|
+
!targetNode.connections.includes(sourceId)) {
|
|
125
|
+
targetNode.connections.push(sourceId);
|
|
126
|
+
}
|
|
127
|
+
return edge;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Remove an edge
|
|
131
|
+
*/
|
|
132
|
+
removeEdge(edgeId) {
|
|
133
|
+
const edge = this.edges.get(edgeId);
|
|
134
|
+
if (!edge) {
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
// Update node connections
|
|
138
|
+
const sourceNode = this.nodes.get(edge.sourceId);
|
|
139
|
+
const targetNode = this.nodes.get(edge.targetId);
|
|
140
|
+
if (sourceNode) {
|
|
141
|
+
sourceNode.connections = sourceNode.connections.filter((id) => id !== edge.targetId);
|
|
142
|
+
}
|
|
143
|
+
if (targetNode && edge.type === "bidirectional") {
|
|
144
|
+
targetNode.connections = targetNode.connections.filter((id) => id !== edge.sourceId);
|
|
145
|
+
}
|
|
146
|
+
this.edges.delete(edgeId);
|
|
147
|
+
return true;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Build star topology (hub and spoke)
|
|
151
|
+
*/
|
|
152
|
+
buildStarTopology(agents) {
|
|
153
|
+
if (agents.length === 0) {
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
// Find or create coordinator
|
|
157
|
+
let coordinatorNode;
|
|
158
|
+
if (this.config.coordinatorId) {
|
|
159
|
+
coordinatorNode = Array.from(this.nodes.values()).find((n) => n.agentId === this.config.coordinatorId);
|
|
160
|
+
}
|
|
161
|
+
if (!coordinatorNode) {
|
|
162
|
+
// Use first agent as coordinator
|
|
163
|
+
coordinatorNode = Array.from(this.nodes.values())[0];
|
|
164
|
+
}
|
|
165
|
+
coordinatorNode.role = "coordinator";
|
|
166
|
+
// Connect all other nodes to coordinator
|
|
167
|
+
for (const node of this.nodes.values()) {
|
|
168
|
+
if (node.id !== coordinatorNode.id) {
|
|
169
|
+
node.role = "worker";
|
|
170
|
+
this.addEdge(coordinatorNode.id, node.id);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Build mesh topology (fully connected)
|
|
176
|
+
*/
|
|
177
|
+
buildMeshTopology(_agents) {
|
|
178
|
+
const nodeArray = Array.from(this.nodes.values());
|
|
179
|
+
// Connect every node to every other node
|
|
180
|
+
for (let i = 0; i < nodeArray.length; i++) {
|
|
181
|
+
nodeArray[i].role = "peer";
|
|
182
|
+
for (let j = i + 1; j < nodeArray.length; j++) {
|
|
183
|
+
this.addEdge(nodeArray[i].id, nodeArray[j].id);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Build hierarchical topology (tree)
|
|
189
|
+
*/
|
|
190
|
+
buildHierarchicalTopology(agents) {
|
|
191
|
+
if (agents.length === 0) {
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
const nodeArray = Array.from(this.nodes.values());
|
|
195
|
+
const maxChildren = this.config.maxChildren ?? 3;
|
|
196
|
+
if (maxChildren < 1) {
|
|
197
|
+
throw new Error(`[NetworkTopology] maxChildren must be >= 1, got ${maxChildren}. ` +
|
|
198
|
+
`A value of 0 or less would orphan every non-root node because no ` +
|
|
199
|
+
`children can ever be assigned to a parent.`);
|
|
200
|
+
}
|
|
201
|
+
// Find or set root
|
|
202
|
+
let rootNode;
|
|
203
|
+
if (this.config.rootId) {
|
|
204
|
+
rootNode = nodeArray.find((n) => n.agentId === this.config.rootId);
|
|
205
|
+
}
|
|
206
|
+
if (!rootNode) {
|
|
207
|
+
rootNode = nodeArray[0];
|
|
208
|
+
}
|
|
209
|
+
rootNode.role = "supervisor";
|
|
210
|
+
const assigned = new Set([rootNode.id]);
|
|
211
|
+
const queue = [rootNode];
|
|
212
|
+
let nodeIndex = 1; // Start from second node
|
|
213
|
+
while (queue.length > 0 && nodeIndex < nodeArray.length) {
|
|
214
|
+
const parent = queue.shift();
|
|
215
|
+
let childCount = 0;
|
|
216
|
+
while (childCount < maxChildren && nodeIndex < nodeArray.length) {
|
|
217
|
+
const child = nodeArray[nodeIndex];
|
|
218
|
+
if (!assigned.has(child.id)) {
|
|
219
|
+
// Set parent-child relationship
|
|
220
|
+
child.parentId = parent.id;
|
|
221
|
+
parent.childIds.push(child.id);
|
|
222
|
+
child.role =
|
|
223
|
+
nodeIndex < nodeArray.length - maxChildren
|
|
224
|
+
? "supervisor"
|
|
225
|
+
: "worker";
|
|
226
|
+
// Add edge
|
|
227
|
+
this.addEdge(parent.id, child.id, "unidirectional");
|
|
228
|
+
assigned.add(child.id);
|
|
229
|
+
queue.push(child);
|
|
230
|
+
childCount++;
|
|
231
|
+
}
|
|
232
|
+
nodeIndex++;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Build ring topology
|
|
238
|
+
*/
|
|
239
|
+
buildRingTopology(_agents) {
|
|
240
|
+
const nodeArray = Array.from(this.nodes.values());
|
|
241
|
+
if (nodeArray.length === 0) {
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
// Connect each node to the next, and last to first
|
|
245
|
+
for (let i = 0; i < nodeArray.length; i++) {
|
|
246
|
+
nodeArray[i].role = "peer";
|
|
247
|
+
const nextIndex = (i + 1) % nodeArray.length;
|
|
248
|
+
this.addEdge(nodeArray[i].id, nodeArray[nextIndex].id, "unidirectional");
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Build custom topology from configuration
|
|
253
|
+
*/
|
|
254
|
+
buildCustomTopology(_agents) {
|
|
255
|
+
if (!this.config.customEdges) {
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
// Create node lookup by agent ID
|
|
259
|
+
const nodeByAgentId = new Map();
|
|
260
|
+
for (const node of this.nodes.values()) {
|
|
261
|
+
nodeByAgentId.set(node.agentId, node);
|
|
262
|
+
node.role = "peer";
|
|
263
|
+
}
|
|
264
|
+
// Add custom edges
|
|
265
|
+
for (const edge of this.config.customEdges) {
|
|
266
|
+
const sourceNode = nodeByAgentId.get(edge.source);
|
|
267
|
+
const targetNode = nodeByAgentId.get(edge.target);
|
|
268
|
+
if (sourceNode && targetNode) {
|
|
269
|
+
this.addEdge(sourceNode.id, targetNode.id, edge.bidirectional !== false ? "bidirectional" : "unidirectional");
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Get node by ID
|
|
275
|
+
*/
|
|
276
|
+
getNode(nodeId) {
|
|
277
|
+
return this.nodes.get(nodeId);
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Get node by agent ID
|
|
281
|
+
*/
|
|
282
|
+
getNodeByAgentId(agentId) {
|
|
283
|
+
for (const node of this.nodes.values()) {
|
|
284
|
+
if (node.agentId === agentId) {
|
|
285
|
+
return node;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
return undefined;
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Get all nodes
|
|
292
|
+
*/
|
|
293
|
+
getAllNodes() {
|
|
294
|
+
return Array.from(this.nodes.values());
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Get all edges
|
|
298
|
+
*/
|
|
299
|
+
getAllEdges() {
|
|
300
|
+
return Array.from(this.edges.values());
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Get connected nodes
|
|
304
|
+
*/
|
|
305
|
+
getConnectedNodes(nodeId) {
|
|
306
|
+
const node = this.nodes.get(nodeId);
|
|
307
|
+
if (!node) {
|
|
308
|
+
return [];
|
|
309
|
+
}
|
|
310
|
+
return node.connections
|
|
311
|
+
.map((id) => this.nodes.get(id))
|
|
312
|
+
.filter((n) => n !== undefined);
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Find shortest path between two nodes (BFS)
|
|
316
|
+
*/
|
|
317
|
+
findShortestPath(sourceId, targetId) {
|
|
318
|
+
if (sourceId === targetId) {
|
|
319
|
+
return [sourceId];
|
|
320
|
+
}
|
|
321
|
+
const visited = new Set();
|
|
322
|
+
const queue = [
|
|
323
|
+
{ nodeId: sourceId, path: [sourceId] },
|
|
324
|
+
];
|
|
325
|
+
while (queue.length > 0) {
|
|
326
|
+
const { nodeId, path } = queue.shift();
|
|
327
|
+
if (visited.has(nodeId)) {
|
|
328
|
+
continue;
|
|
329
|
+
}
|
|
330
|
+
visited.add(nodeId);
|
|
331
|
+
const node = this.nodes.get(nodeId);
|
|
332
|
+
if (!node) {
|
|
333
|
+
continue;
|
|
334
|
+
}
|
|
335
|
+
for (const connectedId of node.connections) {
|
|
336
|
+
if (connectedId === targetId) {
|
|
337
|
+
return [...path, targetId];
|
|
338
|
+
}
|
|
339
|
+
if (!visited.has(connectedId)) {
|
|
340
|
+
queue.push({ nodeId: connectedId, path: [...path, connectedId] });
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
return undefined; // No path found
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Check if two nodes are connected (directly or indirectly)
|
|
348
|
+
*/
|
|
349
|
+
areConnected(sourceId, targetId) {
|
|
350
|
+
return this.findShortestPath(sourceId, targetId) !== undefined;
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Get nodes by role
|
|
354
|
+
*/
|
|
355
|
+
getNodesByRole(role) {
|
|
356
|
+
return Array.from(this.nodes.values()).filter((n) => n.role === role);
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Get coordinator/root node
|
|
360
|
+
*/
|
|
361
|
+
getCoordinator() {
|
|
362
|
+
return (Array.from(this.nodes.values()).find((n) => n.role === "coordinator") ||
|
|
363
|
+
Array.from(this.nodes.values()).find((n) => n.role === "supervisor" && !n.parentId));
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* Calculate topology statistics
|
|
367
|
+
*/
|
|
368
|
+
getStats() {
|
|
369
|
+
const nodes = Array.from(this.nodes.values());
|
|
370
|
+
const nodeCount = nodes.length;
|
|
371
|
+
const edgeCount = this.edges.size;
|
|
372
|
+
if (nodeCount === 0) {
|
|
373
|
+
return {
|
|
374
|
+
nodeCount: 0,
|
|
375
|
+
edgeCount: 0,
|
|
376
|
+
avgConnections: 0,
|
|
377
|
+
maxConnections: 0,
|
|
378
|
+
minConnections: 0,
|
|
379
|
+
diameter: 0,
|
|
380
|
+
density: 0,
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
const connectionCounts = nodes.map((n) => n.connections.length);
|
|
384
|
+
const maxConnections = Math.max(...connectionCounts);
|
|
385
|
+
const minConnections = Math.min(...connectionCounts);
|
|
386
|
+
const avgConnections = connectionCounts.reduce((a, b) => a + b, 0) / nodeCount;
|
|
387
|
+
// Calculate diameter (max shortest path)
|
|
388
|
+
let diameter = 0;
|
|
389
|
+
for (const source of nodes) {
|
|
390
|
+
for (const target of nodes) {
|
|
391
|
+
if (source.id !== target.id) {
|
|
392
|
+
const path = this.findShortestPath(source.id, target.id);
|
|
393
|
+
if (path && path.length - 1 > diameter) {
|
|
394
|
+
diameter = path.length - 1;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
// Calculate density
|
|
400
|
+
const maxPossibleEdges = (nodeCount * (nodeCount - 1)) / 2;
|
|
401
|
+
const density = maxPossibleEdges > 0 ? edgeCount / maxPossibleEdges : 0;
|
|
402
|
+
return {
|
|
403
|
+
nodeCount,
|
|
404
|
+
edgeCount,
|
|
405
|
+
avgConnections,
|
|
406
|
+
maxConnections,
|
|
407
|
+
minConnections,
|
|
408
|
+
diameter,
|
|
409
|
+
density,
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* Export topology as JSON
|
|
414
|
+
*/
|
|
415
|
+
toJSON() {
|
|
416
|
+
return {
|
|
417
|
+
id: this.topologyId,
|
|
418
|
+
type: this.config.type,
|
|
419
|
+
nodes: Array.from(this.nodes.values()),
|
|
420
|
+
edges: Array.from(this.edges.values()),
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
/**
|
|
424
|
+
* Import topology from JSON
|
|
425
|
+
*/
|
|
426
|
+
fromJSON(data) {
|
|
427
|
+
// Restore the original topology id so round-trips preserve identity
|
|
428
|
+
if (data.id !== undefined) {
|
|
429
|
+
this.topologyId = data.id;
|
|
430
|
+
}
|
|
431
|
+
this.config.type = data.type;
|
|
432
|
+
this.nodes.clear();
|
|
433
|
+
this.edges.clear();
|
|
434
|
+
for (const node of data.nodes) {
|
|
435
|
+
this.nodes.set(node.id, node);
|
|
436
|
+
}
|
|
437
|
+
for (const edge of data.edges) {
|
|
438
|
+
this.edges.set(edge.id, edge);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
/**
|
|
442
|
+
* Get topology type
|
|
443
|
+
*/
|
|
444
|
+
getType() {
|
|
445
|
+
return this.config.type;
|
|
446
|
+
}
|
|
447
|
+
/**
|
|
448
|
+
* Get topology ID
|
|
449
|
+
*/
|
|
450
|
+
getId() {
|
|
451
|
+
return this.topologyId;
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
/**
|
|
455
|
+
* Topology builder for fluent API
|
|
456
|
+
*/
|
|
457
|
+
export class TopologyBuilder {
|
|
458
|
+
agents = [];
|
|
459
|
+
config;
|
|
460
|
+
constructor(type) {
|
|
461
|
+
this.config = { type };
|
|
462
|
+
}
|
|
463
|
+
/**
|
|
464
|
+
* Add an agent
|
|
465
|
+
*/
|
|
466
|
+
addAgent(agent) {
|
|
467
|
+
this.agents.push(agent);
|
|
468
|
+
return this;
|
|
469
|
+
}
|
|
470
|
+
/**
|
|
471
|
+
* Add multiple agents
|
|
472
|
+
*/
|
|
473
|
+
addAgents(agents) {
|
|
474
|
+
this.agents.push(...agents);
|
|
475
|
+
return this;
|
|
476
|
+
}
|
|
477
|
+
/**
|
|
478
|
+
* Set coordinator (for star topology)
|
|
479
|
+
*/
|
|
480
|
+
setCoordinator(agentId) {
|
|
481
|
+
this.config.coordinatorId = agentId;
|
|
482
|
+
return this;
|
|
483
|
+
}
|
|
484
|
+
/**
|
|
485
|
+
* Set root (for hierarchical topology)
|
|
486
|
+
*/
|
|
487
|
+
setRoot(agentId) {
|
|
488
|
+
this.config.rootId = agentId;
|
|
489
|
+
return this;
|
|
490
|
+
}
|
|
491
|
+
/**
|
|
492
|
+
* Set max children (for hierarchical topology)
|
|
493
|
+
*/
|
|
494
|
+
setMaxChildren(max) {
|
|
495
|
+
this.config.maxChildren = max;
|
|
496
|
+
return this;
|
|
497
|
+
}
|
|
498
|
+
/**
|
|
499
|
+
* Add custom edge
|
|
500
|
+
*/
|
|
501
|
+
addCustomEdge(sourceAgentId, targetAgentId, bidirectional = true) {
|
|
502
|
+
if (!this.config.customEdges) {
|
|
503
|
+
this.config.customEdges = [];
|
|
504
|
+
}
|
|
505
|
+
this.config.customEdges.push({
|
|
506
|
+
source: sourceAgentId,
|
|
507
|
+
target: targetAgentId,
|
|
508
|
+
bidirectional,
|
|
509
|
+
});
|
|
510
|
+
return this;
|
|
511
|
+
}
|
|
512
|
+
/**
|
|
513
|
+
* Build the topology
|
|
514
|
+
*/
|
|
515
|
+
build() {
|
|
516
|
+
const topology = new NetworkTopology(this.config);
|
|
517
|
+
topology.buildFromAgents(this.agents);
|
|
518
|
+
return topology;
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
//# sourceMappingURL=topology.js.map
|