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

310 lines (309 loc) 10.7 kB
import { Logger } from "@hashgraphonline/standards-sdk"; import { EntityFormat } from "./index27.js"; import "./index29.js"; class ParameterService { constructor(formatConverterRegistry, networkType) { this.logger = new Logger({ module: "ParameterService" }); this.formatConverterRegistry = formatConverterRegistry; this.networkType = networkType; } /** * Unified preprocessing entrypoint (DRY): * - Optional AI-driven resolution via provided entityResolver * - Deterministic post-pass for safe format enforcement */ async preprocessParameters(toolName, parameters, entities = [], options) { const sessionId = options?.sessionId; const entityResolver = options?.entityResolver; const preferences = options?.preferences; let working = { ...parameters }; if (entityResolver && entities.length > 0) { try { this.logger.info("AI-driven preprocessing phase", { toolName, entityCount: entities.length, sessionId }); const aiProcessed = { ...working }; for (const [paramName, paramValue] of Object.entries(working)) { if (typeof paramValue === "string") { const resolved = await entityResolver.resolveReferences( paramValue, entities ); const converted = await this.convertParameterEntities( resolved, entities, preferences ); aiProcessed[paramName] = converted; } else if (Array.isArray(paramValue)) { const out = []; for (const item of paramValue) { if (typeof item === "string") { const resolved = await entityResolver.resolveReferences( item, entities ); const converted = await this.convertParameterEntities( resolved, entities, preferences ); out.push(converted); } else { out.push(item); } } aiProcessed[paramName] = out; } } working = aiProcessed; } catch (error) { const message = error instanceof Error ? error.message : "unknown"; this.logger.warn( "AI phase failed; continuing with deterministic pass", { toolName, error: message } ); } } try { const processed = { ...working }; for (const [paramName, paramValue] of Object.entries(working)) { if (typeof paramValue === "string") { const converted = await this.convertParameterEntities( paramValue, entities, preferences ); processed[paramName] = converted; } else if (Array.isArray(paramValue)) { const out = []; for (const item of paramValue) { if (typeof item === "string") { const converted = await this.convertParameterEntities( item, entities, preferences ); out.push(converted); } else { out.push(item); } } processed[paramName] = out; } } working = processed; } catch (e) { this.logger.warn("Deterministic post-pass failed", { toolName, error: e instanceof Error ? e.message : "unknown" }); } return working; } /** * Attach unified preprocessing callback directly to the agent. */ attachToAgent(agent, deps) { const getSessionId = deps?.getSessionId ?? (() => null); const getEntities = deps?.getEntities ?? (async () => []); const entityResolver = deps?.entityResolver; const maybe = agent; const attach = (target) => { const t = target; if (typeof t.setParameterPreprocessingCallback === "function") { t.setParameterPreprocessingCallback( async (toolName, parameters) => { const sessionId = getSessionId(); const entities = await getEntities(sessionId); const opts = {}; if (entityResolver) { opts.entityResolver = entityResolver; } if (sessionId) { opts.sessionId = sessionId; } return this.preprocessParameters(toolName, parameters, entities, opts); } ); this.logger.info("Parameter preprocessing callback attached"); return true; } return false; }; if (!attach(agent) && typeof maybe.getAgent === "function") { const underlying = maybe.getAgent(); if (underlying) { void attach(underlying); } } } /** * Preprocess tool parameters by applying format conversions based on tool's entity resolution preferences */ async preprocessToolParameters(toolName, parameters, entities, sessionId) { try { if (!entities || entities.length === 0) { this.logger.info( "Tool parameter preprocessing skipped - no entities provided:", { toolName, originalParams: Object.keys(parameters) } ); return parameters; } const processedParameters = { ...parameters }; const preferences = void 0; let hasChanges = false; for (const [paramName, paramValue] of Object.entries(parameters)) { if (typeof paramValue === "string") { const convertedValue = await this.convertParameterEntities( paramValue, entities, preferences ); if (convertedValue !== paramValue) { processedParameters[paramName] = convertedValue; hasChanges = true; this.logger.info("Parameter entity conversion applied:", { toolName, paramName, original: paramValue, converted: convertedValue }); } } else if (Array.isArray(paramValue)) { const originalArray = paramValue; const convertedArray = []; let arrayChanged = false; for (const item of originalArray) { if (typeof item === "string") { const convertedItem = await this.convertParameterEntities( item, entities, preferences ); convertedArray.push(convertedItem); if (convertedItem !== item) { arrayChanged = true; this.logger.info("Parameter array item conversion applied:", { toolName, paramName, original: item, converted: convertedItem }); } } else { convertedArray.push(item); } } if (arrayChanged) { processedParameters[paramName] = convertedArray; hasChanges = true; } } } this.logger.info("Tool parameter preprocessing completed:", { toolName, originalParams: Object.keys(parameters), hasChanges, sessionId }); return processedParameters; } catch (error) { this.logger.warn("Tool parameter preprocessing failed:", { toolName, error: error instanceof Error ? error.message : "Unknown error" }); return parameters; } } /** * Convert entity references in a parameter value based on tool preferences */ async convertParameterEntities(parameterValue, entities, preferences) { let convertedValue = parameterValue; for (const entity of entities) { const containsEntityId = convertedValue.includes(entity.entityId); const containsEntityName = convertedValue.includes(entity.entityName); if (!containsEntityId && !containsEntityName) { continue; } let targetFormat = null; if (entity.entityType === EntityFormat.TOPIC_ID) { if (preferences?.inscription === "hrl" || preferences?.topic === "hrl") { targetFormat = EntityFormat.HRL; } else if (preferences?.inscription === "topicId" || preferences?.topic === "topicId") { targetFormat = EntityFormat.TOPIC_ID; } } else if (entity.entityType === EntityFormat.TOKEN_ID) { if (preferences?.token === "tokenId") { targetFormat = EntityFormat.TOKEN_ID; } else if (preferences?.token === "symbol") { targetFormat = EntityFormat.SYMBOL; } } else if (entity.entityType === EntityFormat.ACCOUNT_ID) { if (preferences?.account === "accountId" || preferences?.supplyKey === "accountId" || preferences?.adminKey === "accountId") { targetFormat = EntityFormat.ACCOUNT_ID; } else if (preferences?.account === "alias") { targetFormat = EntityFormat.ALIAS; } } if (targetFormat) { try { const context = { networkType: this.networkType, sessionId: "unknown" }; if (preferences) { context.toolPreferences = preferences; } const convertedEntityValue = await this.formatConverterRegistry.convertEntity( entity.entityId, targetFormat, context ); if (containsEntityId) { convertedValue = convertedValue.replace( new RegExp(`\\b${entity.entityId.replace(/\./g, "\\.")}\\b`, "g"), convertedEntityValue ); } if (containsEntityName) { convertedValue = convertedValue.replace( new RegExp( `\\b${entity.entityName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\b`, "g" ), convertedEntityValue ); } this.logger.info("Applied format conversion to parameter:", { entityId: entity.entityId, entityType: entity.entityType, targetFormat, convertedValue: convertedEntityValue, parameterValue: convertedValue }); } catch (error) { this.logger.warn("Format conversion failed for parameter:", { entityId: entity.entityId, targetFormat, error: error instanceof Error ? error.message : "Unknown error" }); } } } return convertedValue; } } export { ParameterService }; //# sourceMappingURL=index30.js.map