UNPKG

@agentdao/core

Version:

Core functionality, skills, and ready-made UI components for AgentDAO - Web3 subscriptions, content generation, social media, help support, live chat, RSS fetching, web search, and agent pricing integration

439 lines (438 loc) 16.2 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.A2AProtocolSkill = void 0; const axios_1 = __importDefault(require("axios")); class A2AProtocolSkill { constructor(config) { this.activeTasks = new Map(); this.agentRegistry = new Map(); this.messageQueue = []; this.isRunning = false; this.config = config; this.validateConfig(); } /** * Initialize the A2A Protocol skill */ async initialize() { try { // Register this agent in the A2A registry if (this.config.discovery.enabled && this.config.discovery.autoRegister) { await this.registerAgent(); } // Start discovery service if (this.config.discovery.enabled) { await this.startDiscoveryService(); } // Start message processing this.startMessageProcessor(); console.log(`A2A Protocol initialized for agent: ${this.config.agentName}`); } catch (error) { console.error('Failed to initialize A2A Protocol:', error); throw error; } } /** * Register this agent in the A2A registry */ async registerAgent() { const agent = { id: this.config.agentId, name: this.config.agentName, description: this.config.agentDescription, capabilities: this.config.capabilities, endpoint: this.config.endpoint, version: this.config.version, framework: this.config.framework, metadata: { registeredAt: new Date().toISOString(), lastHeartbeat: new Date().toISOString() } }; if (this.config.discovery.registryUrl) { try { await axios_1.default.post(`${this.config.discovery.registryUrl}/agents`, agent, { headers: this.getAuthHeaders() }); console.log(`Agent registered in A2A registry: ${this.config.agentName}`); } catch (error) { console.warn('Failed to register agent in external registry:', error); } } // Add to local registry this.agentRegistry.set(this.config.agentId, agent); } /** * Discover available agents */ async discoverAgents(filters) { const discoveredAgents = []; // Query external registry if (this.config.discovery.registryUrl) { try { const response = await axios_1.default.get(`${this.config.discovery.registryUrl}/agents`, { params: filters, headers: this.getAuthHeaders() }); discoveredAgents.push(...response.data.agents); } catch (error) { console.warn('Failed to query external registry:', error); } } // Add local registry agents discoveredAgents.push(...Array.from(this.agentRegistry.values())); // Apply filters if (filters) { return discoveredAgents.filter(agent => { return Object.entries(filters).every(([key, value]) => { if (key === 'capabilities') { return Array.isArray(value) ? value.some(cap => agent.capabilities.includes(cap)) : agent.capabilities.includes(value); } return agent[key] === value; }); }); } return discoveredAgents; } /** * Send a task to another agent */ async delegateTask(targetAgentId, task, options) { const targetAgent = this.agentRegistry.get(targetAgentId); if (!targetAgent) { throw new Error(`Target agent not found: ${targetAgentId}`); } const message = { id: this.generateMessageId(), fromAgent: this.config.agentId, toAgent: targetAgentId, task: { ...task, id: this.generateTaskId(), priority: options?.priority || 'medium', timeout: options?.timeout || this.config.taskManagement.taskTimeout }, timestamp: new Date(), status: 'pending', metadata: options?.metadata }; // Add to active tasks this.activeTasks.set(message.id, message); try { // Send task to target agent const response = await axios_1.default.post(`${targetAgent.endpoint}/a2a/tasks`, message, { headers: this.getAuthHeaders(), timeout: message.task.timeout }); // Update message status message.status = 'processing'; this.activeTasks.set(message.id, message); return message; } catch (error) { message.status = 'failed'; message.error = error instanceof Error ? error.message : 'Unknown error'; this.activeTasks.set(message.id, message); throw error; } } /** * Send a streaming task to another agent */ async streamTask(targetAgentId, task, onChunk, options) { const targetAgent = this.agentRegistry.get(targetAgentId); if (!targetAgent) { throw new Error(`Target agent not found: ${targetAgentId}`); } const message = { id: this.generateMessageId(), fromAgent: this.config.agentId, toAgent: targetAgentId, task: { ...task, id: this.generateTaskId(), type: 'stream', priority: options?.priority || 'medium', timeout: options?.timeout || this.config.streaming.maxStreamDuration }, timestamp: new Date(), status: 'pending' }; try { // Use Server-Sent Events for streaming const eventSource = new EventSource(`${targetAgent.endpoint}/a2a/stream/${message.id}`); eventSource.onmessage = (event) => { const chunk = JSON.parse(event.data); onChunk(chunk); if (chunk.isComplete) { eventSource.close(); message.status = 'completed'; this.activeTasks.set(message.id, message); } }; eventSource.onerror = (error) => { eventSource.close(); message.status = 'failed'; message.error = 'Streaming error'; this.activeTasks.set(message.id, message); throw error; }; // Send initial task await axios_1.default.post(`${targetAgent.endpoint}/a2a/stream`, message, { headers: this.getAuthHeaders(), timeout: message.task.timeout }); } catch (error) { message.status = 'failed'; message.error = error instanceof Error ? error.message : 'Unknown error'; this.activeTasks.set(message.id, message); throw error; } } /** * Collaborate with multiple agents on a complex task */ async collaborate(agentIds, task, coordinationStrategy = 'parallel') { const results = []; switch (coordinationStrategy) { case 'parallel': // Execute tasks in parallel const promises = agentIds.map(agentId => this.delegateTask(agentId, task).then(msg => this.waitForCompletion(msg.id))); results.push(...await Promise.all(promises)); break; case 'sequential': // Execute tasks sequentially for (const agentId of agentIds) { const message = await this.delegateTask(agentId, task); const result = await this.waitForCompletion(message.id); results.push(result); } break; case 'hierarchical': // Execute with a coordinator agent const coordinatorId = agentIds[0]; const subAgents = agentIds.slice(1); const coordinationTask = { ...task, id: this.generateTaskId(), type: 'delegate', input: { ...task.input, subAgents, coordinationType: 'hierarchical' } }; const message = await this.delegateTask(coordinatorId, coordinationTask); const result = await this.waitForCompletion(message.id); results.push(result); break; } return results; } /** * Wait for task completion */ async waitForCompletion(messageId, timeout) { const startTime = Date.now(); const maxWait = timeout || this.config.taskManagement.taskTimeout; while (Date.now() - startTime < maxWait) { const message = this.activeTasks.get(messageId); if (!message) { throw new Error(`Message not found: ${messageId}`); } if (message.status === 'completed') { return { success: true, data: message.result, metadata: message.metadata, executionTime: Date.now() - startTime }; } if (message.status === 'failed') { return { success: false, error: message.error, metadata: message.metadata, executionTime: Date.now() - startTime }; } // Wait before checking again await new Promise(resolve => setTimeout(resolve, 100)); } throw new Error(`Task timeout: ${messageId}`); } /** * Handle incoming tasks from other agents */ async handleIncomingTask(message) { // Validate message if (message.toAgent !== this.config.agentId) { throw new Error('Message not intended for this agent'); } // Check security if (this.config.security.enabled) { if (this.config.security.allowedAgents && !this.config.security.allowedAgents.includes(message.fromAgent)) { throw new Error('Unauthorized agent'); } } // Process task based on type switch (message.task.type) { case 'delegate': return await this.processDelegatedTask(message); case 'collaborate': return await this.processCollaborationTask(message); case 'query': return await this.processQueryTask(message); case 'stream': return await this.processStreamingTask(message); default: throw new Error(`Unknown task type: ${message.task.type}`); } } /** * Process delegated tasks */ async processDelegatedTask(message) { try { // This is where you would implement your agent's specific logic // For now, we'll return a placeholder response const result = { taskId: message.task.id, processedBy: this.config.agentName, input: message.task.input, output: `Task processed by ${this.config.agentName}`, timestamp: new Date().toISOString() }; // Update message status message.status = 'completed'; message.result = result; this.activeTasks.set(message.id, message); return { success: true, data: result, executionTime: Date.now() - message.timestamp.getTime() }; } catch (error) { message.status = 'failed'; message.error = error instanceof Error ? error.message : 'Unknown error'; this.activeTasks.set(message.id, message); return { success: false, error: message.error, executionTime: Date.now() - message.timestamp.getTime() }; } } /** * Process collaboration tasks */ async processCollaborationTask(message) { // Implement collaboration logic return await this.processDelegatedTask(message); } /** * Process query tasks */ async processQueryTask(message) { // Implement query logic return await this.processDelegatedTask(message); } /** * Process streaming tasks */ async processStreamingTask(message) { // Implement streaming logic return await this.processDelegatedTask(message); } /** * Get agent status and health */ getAgentStatus() { return { agentId: this.config.agentId, agentName: this.config.agentName, status: this.isRunning ? 'online' : 'offline', activeTasks: this.activeTasks.size, capabilities: this.config.capabilities, lastHeartbeat: new Date() }; } /** * Get task statistics */ getTaskStats() { const tasks = Array.from(this.activeTasks.values()); const completed = tasks.filter(t => t.status === 'completed').length; const failed = tasks.filter(t => t.status === 'failed').length; const pending = tasks.filter(t => t.status === 'pending' || t.status === 'processing').length; return { totalTasks: tasks.length, completedTasks: completed, failedTasks: failed, pendingTasks: pending, averageExecutionTime: 0 // Calculate based on completed tasks }; } // Private helper methods validateConfig() { if (!this.config.agentId || !this.config.agentName || !this.config.endpoint) { throw new Error('Missing required A2A configuration: agentId, agentName, endpoint'); } } getAuthHeaders() { const headers = { 'Content-Type': 'application/json', 'User-Agent': `AgentDAO-A2A/${this.config.version}` }; if (this.config.security.apiKey) { headers['Authorization'] = `Bearer ${this.config.security.apiKey}`; } return headers; } generateMessageId() { return `msg_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; } generateTaskId() { return `task_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; } async startDiscoveryService() { // Start periodic agent discovery setInterval(async () => { try { const agents = await this.discoverAgents(); agents.forEach(agent => { this.agentRegistry.set(agent.id, agent); }); } catch (error) { console.warn('Discovery service error:', error); } }, this.config.discovery.heartbeatInterval); } startMessageProcessor() { this.isRunning = true; // Process message queue setInterval(() => { while (this.messageQueue.length > 0) { const message = this.messageQueue.shift(); if (message) { this.handleIncomingTask(message).catch(error => { console.error('Failed to process message:', error); }); } } }, 100); } } exports.A2AProtocolSkill = A2AProtocolSkill;