UNPKG

@hashgraphonline/standards-agent-kit

Version:

A modular SDK for building on-chain autonomous agents using Hashgraph Online Standards, including HCS-10 for agent discovery and communication.

174 lines (156 loc) 5.36 kB
import { StructuredTool, ToolParams } from '@langchain/core/tools'; import { z } from 'zod'; import { IStateManager, } from '../state/state-types'; import { HCS10Client } from '../hcs10/HCS10Client'; import { Logger, Connection, } from '@hashgraphonline/standards-sdk'; type ListPendingRequestsToolParams = ToolParams & { hcsClient: HCS10Client; stateManager: IStateManager; }; export class ListUnapprovedConnectionRequestsTool extends StructuredTool { name = 'list_unapproved_connection_requests'; description = 'Lists all connection requests that are not fully established, including incoming requests needing approval and outgoing requests waiting for confirmation.'; schema = z.object({ sortBy: z .enum(['time_asc', 'time_desc', 'name_asc', 'name_desc']) .optional() .describe( 'Optional sorting criteria for the requests list (default: time_desc, newest first)' ), limit: z .number() .optional() .describe( 'Optional limit on the number of requests to return (default: all)' ), }); private hcsClient: HCS10Client; private stateManager: IStateManager; private logger: Logger; constructor({ hcsClient, stateManager, ...rest }: ListPendingRequestsToolParams) { super(rest); this.hcsClient = hcsClient; this.stateManager = stateManager; this.logger = Logger.getInstance({ module: 'ListPendingRequestsTool', level: 'debug', }); } protected async _call({ sortBy = 'time_desc', limit, }: z.infer<this['schema']>): Promise<string> { const currentAgent = this.stateManager.getCurrentAgent(); if (!currentAgent) { return 'Error: Cannot list pending requests. No agent is currently active. Please register or select an agent first.'; } try { const pendingRequests = await this.findAllPendingRequests(); return this.formatRequestsList(pendingRequests, sortBy, limit); } catch (error) { this.logger.error(`Error in ${this.name}: ${error}`); return `Error listing pending requests: ${ error instanceof Error ? error.message : String(error) }`; } } /** * Processes the connection connectionMap to find all requests * that are not fully established (incoming unapproved and outgoing pending). */ private async findAllPendingRequests(): Promise<Connection[]> { const connectionsManager = this.stateManager.getConnectionsManager(); if (!connectionsManager) { return []; } const currentAgent = this.stateManager.getCurrentAgent(); if (!currentAgent) { return []; } await connectionsManager.fetchConnectionData(currentAgent.accountId); const pendingRequests = connectionsManager.getPendingRequests(); const connectionsNeedingConfirmation = connectionsManager.getConnectionsNeedingConfirmation(); return [...pendingRequests, ...connectionsNeedingConfirmation]; } /** * Formats the list of pending requests for display. */ private formatRequestsList( requests: Connection[], sortBy: string, limit?: number ): string { if (requests.length === 0) { return 'No pending connection requests found (incoming or outgoing).'; } const sortedRequests = this.sortRequests(requests, sortBy); const limitedRequests = limit ? sortedRequests.slice(0, limit) : sortedRequests; let output = `Found ${requests.length} pending connection request(s):\n\n`; limitedRequests.forEach((request, index) => { const statusIndicator = request.status === 'needs_confirmation' ? '🟠 Incoming' : '⚪️ Outgoing'; output += `${index + 1}. ${statusIndicator} - ID: ${request.uniqueRequestKey}\n`; output += ` ${ request.status === 'needs_confirmation' ? 'From:' : 'To: ' } ${request.targetAgentName} (${request.targetAccountId})\n`; output += ` Sent/Rcvd: ${request.created.toLocaleString()}\n`; if (request.memo) { output += ` Memo: ${request.memo}\n`; } if (request.profileInfo?.bio) { output += ` Bio: ${request.profileInfo.bio.substring(0, 100)}${ request.profileInfo.bio.length > 100 ? '...' : '' }\n`; } output += '\n'; }); output += 'Use related tools (manage_requests, accept_request) to handle these items.'; return output; } /** * Sorts connection requests based on the specified criteria. */ private sortRequests( requests: Connection[], sortBy: string ): Connection[] { const requestsCopy = [...requests]; switch (sortBy) { case 'time_asc': return requestsCopy.sort( (a, b) => a.created.getTime() - b.created.getTime() ); case 'time_desc': return requestsCopy.sort( (a, b) => b.created.getTime() - a.created.getTime() ); case 'name_asc': return requestsCopy.sort((a, b) => a.targetAgentName?.localeCompare(b?.targetAgentName || '') || 0 ); case 'name_desc': return requestsCopy.sort((a, b) => b.targetAgentName?.localeCompare(a?.targetAgentName || '') || 0 ); default: return requestsCopy.sort( (a, b) => b.created.getTime() - a.created.getTime() ); } } }