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

158 lines (157 loc) 4.79 kB
import { EntityFormat } from "./index27.js"; import { Logger, HederaMirrorNode } from "@hashgraphonline/standards-sdk"; class FormatConverterRegistry { constructor() { this.converters = /* @__PURE__ */ new Map(); this.entityTypeCache = /* @__PURE__ */ new Map(); this.logger = new Logger({ module: "FormatConverterRegistry" }); this.defaultCacheTTL = 5 * 60 * 1e3; } /** * Register a format converter */ register(converter) { const key = `${converter.sourceFormat}${converter.targetFormat}`; this.converters.set(key, converter); } /** * Find a converter for the given source and target formats */ findConverter(source, target) { const key = `${source}${target}`; return this.converters.get(key) || null; } /** * Convert an entity to the target format */ async convertEntity(entity, target, context) { const sourceFormat = await this.detectFormatWithFallback(entity, context); if (sourceFormat === target) { return entity; } const converter = this.findConverter(sourceFormat, target); if (!converter) { throw new Error(`No converter found for ${sourceFormat}${target}`); } if (!converter.canConvert(entity, context)) { throw new Error(`Converter cannot handle entity: ${entity}`); } const result = await converter.convert(entity, context); return result; } /** * Detect the format of an entity string with API-based verification and fallback */ async detectFormatWithFallback(entity, context) { if (entity.startsWith("hcs://")) { return EntityFormat.HRL; } if (/^0\.0\.\d+$/.test(entity)) { const cached = this.getCachedFormat(entity); if (cached) { return cached; } try { const detected = await this.detectFormat(entity, context || {}); if (detected !== EntityFormat.ANY) { this.setCachedFormat(entity, detected); return detected; } } catch (error) { this.logger.warn( `Entity detection failed for ${entity}, using fallback: ${error.message}` ); } return EntityFormat.ANY; } return EntityFormat.ANY; } /** * Public helper: detect entity format (ACCOUNT_ID, TOKEN_ID, TOPIC_ID, HRL, or ANY) */ async detectEntityFormat(entity, context) { return this.detectFormatWithFallback(entity, context); } /** * Detect entity format via Hedera Mirror Node API calls */ async detectFormat(entity, context) { const networkType = context.networkType || "testnet"; const mirrorNode = new HederaMirrorNode(networkType, this.logger); mirrorNode.configureRetry({ maxRetries: 3, maxDelayMs: 1e3 }); const checks = await Promise.allSettled([ mirrorNode.getAccountBalance(entity).then((result) => result !== null ? EntityFormat.ACCOUNT_ID : null).catch(() => null), mirrorNode.getTokenInfo(entity).then((result) => result !== null ? EntityFormat.TOKEN_ID : null).catch(() => null), mirrorNode.getTopicInfo(entity).then((result) => result !== null ? EntityFormat.TOPIC_ID : null).catch(() => null), mirrorNode.getContract(entity).then((result) => result !== null ? EntityFormat.CONTRACT_ID : null).catch(() => null) ]); const successful = checks.find( (result) => result.status === "fulfilled" && result.value !== null ); return successful && successful.status === "fulfilled" ? successful.value : EntityFormat.ANY; } /** * Get cached entity format if valid */ getCachedFormat(entity) { const entry = this.entityTypeCache.get(entity); if (!entry || this.isCacheExpired(entry)) { this.entityTypeCache.delete(entity); return null; } return entry.format; } /** * Set cached entity format */ setCachedFormat(entity, format) { this.entityTypeCache.set(entity, { format, timestamp: Date.now(), ttl: this.defaultCacheTTL }); } /** * Check if cache entry is expired */ isCacheExpired(entry) { return Date.now() - entry.timestamp > entry.ttl; } /** * Get all registered converters */ getRegisteredConverters() { return Array.from(this.converters.keys()).map((key) => { const [source, target] = key.split("→"); return { source, target }; }); } /** * Check if a converter exists for the given formats */ hasConverter(source, target) { return this.findConverter(source, target) !== null; } /** * Clear all registered converters */ clear() { this.converters.clear(); } /** * Clear entity type cache */ clearCache() { this.entityTypeCache.clear(); } } export { FormatConverterRegistry }; //# sourceMappingURL=index26.js.map