@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
JavaScript
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