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.

133 lines (132 loc) 6.15 kB
import { StructuredTool } from "@langchain/core/tools"; import { z } from "zod"; import { Logger } from "@hashgraphonline/standards-sdk"; class CheckMessagesTool extends StructuredTool { constructor({ hcsClient, stateManager, ...rest }) { super(rest); this.name = "check_messages"; this.description = `Checks for and retrieves messages from an active connection. Identify the target agent using their account ID (e.g., 0.0.12345) or the connection number shown in 'list_connections'. By default, it only retrieves messages newer than the last check. Use 'fetchLatest: true' to get the most recent messages regardless of when they arrived. Use 'lastMessagesCount' to specify how many latest messages to retrieve (default 1 when fetchLatest is true).`; this.schema = z.object({ targetIdentifier: z.string().describe( "The account ID (e.g., 0.0.12345) of the target agent OR the connection number (e.g., '1', '2') from the 'list_connections' tool to check messages for." ), fetchLatest: z.boolean().optional().default(false).describe( "Set to true to fetch the latest messages even if they have been seen before, ignoring the last checked timestamp. Defaults to false (fetching only new messages)." ), lastMessagesCount: z.number().int().positive().optional().describe( "When fetchLatest is true, specifies how many of the most recent messages to retrieve. Defaults to 1." ) }); this.hcsClient = hcsClient; this.stateManager = stateManager; this.logger = Logger.getInstance({ module: "CheckMessagesTool" }); } async _call({ targetIdentifier, fetchLatest, lastMessagesCount }) { const connection = this.stateManager.getConnectionByIdentifier(targetIdentifier); if (!connection) { return `Error: Could not find an active connection matching identifier "${targetIdentifier}". Use 'list_connections' to see active connections.`; } const connectionTopicId = connection.connectionTopicId; const targetAgentName = connection.targetAgentName; const lastProcessedTimestamp = this.stateManager.getLastTimestamp(connectionTopicId); this.logger.info( `Checking messages for connection with ${targetAgentName} (${connection.targetAccountId}) on topic ${connectionTopicId} (fetchLatest: ${fetchLatest}, lastCount: ${lastMessagesCount}, since: ${lastProcessedTimestamp})` ); try { const result = await this.hcsClient.getMessages(connectionTopicId); const allMessages = result.messages; if (!allMessages || allMessages.length === 0) { return `No messages found on connection topic ${connectionTopicId}.`; } let messagesToProcess = []; let latestTimestampNanos = lastProcessedTimestamp; const isFetchingLatest = fetchLatest === true; if (isFetchingLatest) { this.logger.info("Fetching latest messages regardless of timestamp."); const count = lastMessagesCount ?? 1; messagesToProcess = allMessages.slice(-count); } else { this.logger.info( `Filtering for messages newer than ${lastProcessedTimestamp}` ); messagesToProcess = allMessages.filter((msg) => { const msgTimestampNanos = msg.timestamp * 1e6; return msgTimestampNanos > lastProcessedTimestamp; }); if (messagesToProcess.length > 0) { latestTimestampNanos = messagesToProcess.reduce( (maxTs, msg) => Math.max(maxTs, msg.timestamp * 1e6), lastProcessedTimestamp ); } } if (messagesToProcess.length === 0) { return isFetchingLatest ? `Could not retrieve the latest message(s). No messages found on topic ${connectionTopicId}.` : `No new messages found for connection with ${targetAgentName} since last check.`; } this.logger.info(`Processing ${messagesToProcess.length} message(s).`); let outputString = isFetchingLatest ? `Latest message(s) from ${targetAgentName}: ` : `New messages from ${targetAgentName}: `; for (const msg of messagesToProcess) { let content = msg.data; try { if (typeof content === "string" && content.startsWith("hcs://")) { this.logger.debug(`Resolving inscribed message: ${content}`); content = await this.hcsClient.getMessageContent(content); this.logger.debug(`Resolved content length: ${content?.length}`); } let displayContent = content; try { const parsed = JSON.parse(content || "{}"); if (parsed.p === "hcs-10" && parsed.op === "message" && parsed.data) { const senderOpId = parsed.operator_id || "unknown_sender"; displayContent = `[${senderOpId}]: ${parsed.data}`; } else { displayContent = content; } } catch (parseError) { displayContent = content; } const messageDate = new Date(msg.timestamp); outputString += ` [${messageDate.toLocaleString()}] (Seq: ${msg.sequence_number}) ${displayContent} `; } catch (error) { const errorMsg = `Error processing message (Seq: ${msg.sequence_number}): ${error instanceof Error ? error.message : String(error)}`; this.logger.error(errorMsg); outputString += ` [Error processing message Seq: ${msg.sequence_number}] `; } } if (!isFetchingLatest && latestTimestampNanos > lastProcessedTimestamp) { this.logger.debug( `Updating timestamp for topic ${connectionTopicId} to ${latestTimestampNanos}` ); this.stateManager.updateTimestamp( connectionTopicId, latestTimestampNanos ); } return outputString.trim(); } catch (error) { this.logger.error( `Failed to check messages for topic ${connectionTopicId}: ${error}` ); return `Error checking messages for ${targetAgentName}: ${error instanceof Error ? error.message : String(error)}`; } } } export { CheckMessagesTool }; //# sourceMappingURL=standards-agent-kit.es9.js.map