UNPKG

@hashgraphonline/conversational-agent

Version:

Hashgraph Online conversational AI agent implementing HCS-10 communication, HCS-2 registries, and content inscription on Hedera. https://hol.org

130 lines (119 loc) 4.07 kB
import { StructuredTool } from "@langchain/core/tools"; import { z } from "zod"; import { Logger } from "@hashgraphonline/standards-sdk"; const logger = new Logger({ module: "EntityResolverTool" }); const ResolveEntitiesSchema = z.object({ message: z.string().describe("The message containing entity references to resolve"), entities: z.array(z.object({ entityId: z.string(), entityName: z.string(), entityType: z.string() })).describe("Available entities in memory") }); const ExtractEntitiesSchema = z.object({ response: z.string().describe("Agent response text to extract entities from"), userMessage: z.string().describe("Original user message for context") }); class ResolveEntitiesTool extends StructuredTool { constructor(llm) { super(); this.name = "resolve_entities"; this.description = 'Resolves entity references like "the topic", "it", "that" to actual entity IDs'; this.schema = ResolveEntitiesSchema; this.llm = llm; } async _call(input) { const { message, entities } = input; if (!entities || entities.length === 0) { return message; } const byType = this.groupEntitiesByType(entities); const context = this.buildEntityContext(byType); const prompt = `Task: Replace entity references with IDs. ${context} Message: "${message}" Rules: - "the topic" or "that topic" → replace with most recent topic ID - "the token" or "that token" → replace with most recent token ID - "it" or "that" after action verb → replace with most recent entity ID - "airdrop X" without token ID → add most recent token ID as first parameter - Token operations without explicit token → use most recent token ID Examples: - "submit on the topic""submit on 0.0.6543472" - "airdrop the token""airdrop 0.0.123456" - "airdrop 10 to 0.0.5842697""airdrop 0.0.123456 10 to 0.0.5842697" - "mint 100""mint 0.0.123456 100" Return ONLY the resolved message:`; try { const response = await this.llm.invoke(prompt); return response.content.trim(); } catch (error) { logger.error("ResolveEntitiesTool failed:", error); return message; } } groupEntitiesByType(entities) { return entities.reduce((acc, entity) => { if (!acc[entity.entityType]) { acc[entity.entityType] = []; } acc[entity.entityType].push(entity); return acc; }, {}); } buildEntityContext(groupedEntities) { let context = "Available entities:\n"; for (const [type, list] of Object.entries(groupedEntities)) { const recent = list[0]; context += `- Most recent ${type}: "${recent.entityName}" = ${recent.entityId} `; } return context; } } class ExtractEntitiesTool extends StructuredTool { constructor(llm) { super(); this.name = "extract_entities"; this.description = "Extracts newly created entities from agent responses"; this.schema = ExtractEntitiesSchema; this.llm = llm; } async _call(input) { const { response, userMessage } = input; const prompt = `Extract ONLY newly created entities from this response. User asked: "${userMessage.substring(0, 200)}" Response: ${response.substring(0, 3e3)} Look for: - Success messages with new entity IDs - Words like "created", "new", "successfully" followed by entity IDs Return JSON array of created entities: [{"id": "0.0.XXX", "name": "name", "type": "topic|token|account"}] If none created, return: [] JSON:`; try { const llmResponse = await this.llm.invoke(prompt); const content = llmResponse.content; const match = content.match(/\[[\s\S]*?\]/); if (match) { return match[0]; } return "[]"; } catch (error) { logger.error("ExtractEntitiesTool failed:", error); return "[]"; } } } function createEntityTools(llm) { return { resolveEntities: new ResolveEntitiesTool(llm), extractEntities: new ExtractEntitiesTool(llm) }; } export { ExtractEntitiesTool, ResolveEntitiesTool, createEntityTools }; //# sourceMappingURL=index35.js.map