tasq/node_modules/agentic-flow/dist/mcp/fastmcp/tools/swarm/p2p-swarm-tools.js

405 lines
13 KiB
JavaScript

/**
* P2P Swarm V2 MCP Tools
*
* Production-grade P2P swarm coordination exposed as MCP tools.
* Provides decentralized coordination, task execution, and learning sync.
*
* Features:
* - Ed25519/X25519 cryptography
* - GunDB relay coordination
* - Task execution with claim resolution
* - Heartbeat-based liveness
* - Verified member registry
*/
import { z } from 'zod';
import { createP2PSwarmV2 } from '../../../../swarm/p2p-swarm-v2.js';
import { logger } from '../../../../utils/logger.js';
// Global swarm instance for MCP tools
let swarmInstance = null;
/**
* Get or create swarm instance
*/
async function getSwarm(agentId, swarmKey) {
if (!swarmInstance) {
const id = agentId || `mcp-agent-${Date.now().toString(36)}`;
swarmInstance = await createP2PSwarmV2(id, swarmKey);
}
return swarmInstance;
}
/**
* P2P Swarm Connect Tool
*/
export const p2pSwarmConnectTool = {
name: 'p2p_swarm_connect',
description: 'Connect to a P2P swarm for decentralized coordination',
schema: z.object({
agentId: z.string().optional().describe('Agent ID (auto-generated if not provided)'),
swarmKey: z.string().optional().describe('Swarm key to join existing swarm'),
enableExecutor: z.boolean().optional().default(false).describe('Enable task executor'),
}),
execute: async (params) => {
try {
const swarm = await getSwarm(params.agentId, params.swarmKey);
if (params.enableExecutor) {
swarm.startTaskExecutor();
}
const status = swarm.getStatus();
return {
success: true,
connected: status.connected,
agentId: status.agentId,
swarmId: status.swarmId,
swarmKey: swarm.getSwarmKey(),
relays: status.relays,
executorEnabled: params.enableExecutor || false,
};
}
catch (error) {
logger.error('Failed to connect to swarm', { error });
return {
success: false,
error: error instanceof Error ? error.message : String(error),
};
}
},
};
/**
* P2P Swarm Status Tool
*/
export const p2pSwarmStatusTool = {
name: 'p2p_swarm_status',
description: 'Get current P2P swarm status including live members',
schema: z.object({}),
execute: async () => {
if (!swarmInstance) {
return {
success: false,
error: 'Not connected to swarm. Use p2p_swarm_connect first.',
};
}
const status = swarmInstance.getStatus();
const liveMembers = swarmInstance.getLiveMembers();
return {
success: true,
...status,
liveMembers,
liveMemberCount: swarmInstance.getLiveMemberCount(),
};
},
};
/**
* P2P Swarm Members Tool
*/
export const p2pSwarmMembersTool = {
name: 'p2p_swarm_members',
description: 'List swarm members with their capabilities and liveness',
schema: z.object({
includeOffline: z.boolean().optional().default(false).describe('Include offline members'),
}),
execute: async (params) => {
if (!swarmInstance) {
return {
success: false,
error: 'Not connected to swarm. Use p2p_swarm_connect first.',
};
}
const members = swarmInstance.getLiveMembers();
const filtered = params.includeOffline ? members : members.filter(m => m.isAlive);
return {
success: true,
count: filtered.length,
liveCount: filtered.filter(m => m.isAlive).length,
members: filtered.map(m => ({
agentId: m.agentId,
capabilities: m.capabilities,
isAlive: m.isAlive,
lastSeenAgo: Math.round((Date.now() - m.lastSeen) / 1000),
})),
};
},
};
/**
* P2P Swarm Publish Tool
*/
export const p2pSwarmPublishTool = {
name: 'p2p_swarm_publish',
description: 'Publish a signed and encrypted message to a swarm topic',
schema: z.object({
topic: z.string().describe('Topic to publish to'),
payload: z.any().describe('Message payload (will be JSON serialized)'),
}),
execute: async (params) => {
if (!swarmInstance) {
return {
success: false,
error: 'Not connected to swarm. Use p2p_swarm_connect first.',
};
}
try {
const messageId = await swarmInstance.publish(params.topic, params.payload);
return {
success: true,
messageId,
topic: params.topic,
};
}
catch (error) {
return {
success: false,
error: error instanceof Error ? error.message : String(error),
};
}
},
};
/**
* P2P Swarm Subscribe Tool
*/
export const p2pSwarmSubscribeTool = {
name: 'p2p_swarm_subscribe',
description: 'Subscribe to a swarm topic (messages delivered via callback)',
schema: z.object({
topic: z.string().describe('Topic to subscribe to'),
}),
execute: async (params) => {
if (!swarmInstance) {
return {
success: false,
error: 'Not connected to swarm. Use p2p_swarm_connect first.',
};
}
// Note: In MCP context, we return success but messages are handled internally
// For real-time messages, use the streaming MCP transport
swarmInstance.subscribe(params.topic, (data, from) => {
logger.info('Swarm message received', { topic: params.topic, from, data });
});
return {
success: true,
subscribed: params.topic,
note: 'Messages will be logged. Use streaming transport for real-time delivery.',
};
},
};
/**
* P2P Swarm Sync Q-Table Tool
*/
export const p2pSwarmSyncQTableTool = {
name: 'p2p_swarm_sync_qtable',
description: 'Sync a Q-table to the swarm for distributed learning',
schema: z.object({
qTable: z.array(z.array(z.number())).describe('2D array Q-table'),
}),
execute: async (params) => {
if (!swarmInstance) {
return {
success: false,
error: 'Not connected to swarm. Use p2p_swarm_connect first.',
};
}
try {
const pointer = await swarmInstance.syncQTable(params.qTable);
return {
success: true,
cid: pointer.cid,
dimensions: pointer.dimensions,
checksum: pointer.checksum,
timestamp: pointer.timestamp,
};
}
catch (error) {
return {
success: false,
error: error instanceof Error ? error.message : String(error),
};
}
},
};
/**
* P2P Swarm Sync Memory Tool
*/
export const p2pSwarmSyncMemoryTool = {
name: 'p2p_swarm_sync_memory',
description: 'Sync memory vectors to the swarm',
schema: z.object({
vectors: z.array(z.array(z.number())).describe('2D array of vectors'),
namespace: z.string().optional().default('default').describe('Memory namespace'),
}),
execute: async (params) => {
if (!swarmInstance) {
return {
success: false,
error: 'Not connected to swarm. Use p2p_swarm_connect first.',
};
}
try {
const pointer = await swarmInstance.syncMemory(params.vectors, params.namespace || 'default');
return {
success: true,
cid: pointer.cid,
namespace: params.namespace || 'default',
dimensions: pointer.dimensions,
checksum: pointer.checksum,
};
}
catch (error) {
return {
success: false,
error: error instanceof Error ? error.message : String(error),
};
}
},
};
/**
* P2P Swarm Submit Task Tool
*/
export const p2pSwarmSubmitTaskTool = {
name: 'p2p_swarm_submit_task',
description: 'Submit a task for distributed execution',
schema: z.object({
moduleCID: z.string().describe('CID of WASM module'),
inputCID: z.string().describe('CID of input data'),
entrypoint: z.string().optional().default('main').describe('Entrypoint function'),
fuelLimit: z.number().optional().default(1000000).describe('Fuel limit'),
memoryMB: z.number().optional().default(64).describe('Memory limit in MB'),
timeoutMs: z.number().optional().default(30000).describe('Timeout in ms'),
}),
execute: async (params) => {
if (!swarmInstance) {
return {
success: false,
error: 'Not connected to swarm. Use p2p_swarm_connect first.',
};
}
try {
const taskId = `task-${Date.now().toString(36)}`;
const messageId = await swarmInstance.submitTask({
taskId,
moduleCID: params.moduleCID,
inputCID: params.inputCID,
entrypoint: params.entrypoint || 'main',
outputSchemaHash: '',
budgets: {
fuelLimit: params.fuelLimit || 1000000,
memoryMB: params.memoryMB || 64,
timeoutMs: params.timeoutMs || 30000,
},
});
return {
success: true,
taskId,
messageId,
moduleCID: params.moduleCID,
inputCID: params.inputCID,
};
}
catch (error) {
return {
success: false,
error: error instanceof Error ? error.message : String(error),
};
}
},
};
/**
* P2P Swarm Start Executor Tool
*/
export const p2pSwarmStartExecutorTool = {
name: 'p2p_swarm_start_executor',
description: 'Start the task executor to process distributed tasks',
schema: z.object({}),
execute: async () => {
if (!swarmInstance) {
return {
success: false,
error: 'Not connected to swarm. Use p2p_swarm_connect first.',
};
}
swarmInstance.startTaskExecutor();
return {
success: true,
message: 'Task executor started. Listening for tasks.',
};
},
};
/**
* P2P Swarm Stop Executor Tool
*/
export const p2pSwarmStopExecutorTool = {
name: 'p2p_swarm_stop_executor',
description: 'Stop the task executor',
schema: z.object({}),
execute: async () => {
if (!swarmInstance) {
return {
success: false,
error: 'Not connected to swarm.',
};
}
swarmInstance.stopTaskExecutor();
return {
success: true,
message: 'Task executor stopped.',
};
},
};
/**
* P2P Swarm Disconnect Tool
*/
export const p2pSwarmDisconnectTool = {
name: 'p2p_swarm_disconnect',
description: 'Disconnect from the P2P swarm',
schema: z.object({}),
execute: async () => {
if (swarmInstance) {
swarmInstance.disconnect();
swarmInstance = null;
return {
success: true,
message: 'Disconnected from swarm.',
};
}
return {
success: true,
message: 'Not connected to swarm.',
};
},
};
/**
* P2P Swarm Keygen Tool
*/
export const p2pSwarmKeygenTool = {
name: 'p2p_swarm_keygen',
description: 'Generate a new swarm key for creating a new swarm',
schema: z.object({}),
execute: async () => {
const crypto = await import('crypto');
const key = crypto.randomBytes(32).toString('base64');
return {
success: true,
swarmKey: key,
usage: `Use with p2p_swarm_connect: { swarmKey: "${key}" }`,
};
},
};
// Export all tools as array for MCP registration
export const p2pSwarmTools = [
p2pSwarmConnectTool,
p2pSwarmStatusTool,
p2pSwarmMembersTool,
p2pSwarmPublishTool,
p2pSwarmSubscribeTool,
p2pSwarmSyncQTableTool,
p2pSwarmSyncMemoryTool,
p2pSwarmSubmitTaskTool,
p2pSwarmStartExecutorTool,
p2pSwarmStopExecutorTool,
p2pSwarmDisconnectTool,
p2pSwarmKeygenTool,
];
// Export singleton accessor
export function getP2PSwarmInstance() {
return swarmInstance;
}
export function setP2PSwarmInstance(instance) {
swarmInstance = instance;
}
//# sourceMappingURL=p2p-swarm-tools.js.map