@hashgraphonline/conversational-agent 0.2.1 → 0.2.103

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/README.md +3 -3
  2. package/bin/conversational-agent-cli.js +0 -1
  3. package/dist/cjs/conversational-agent.d.ts +11 -1
  4. package/dist/cjs/index.cjs +1 -1
  5. package/dist/cjs/index.cjs.map +1 -1
  6. package/dist/cjs/memory/smart-memory-manager.d.ts +7 -1
  7. package/dist/cjs/services/attachment-processor.d.ts +41 -0
  8. package/dist/cjs/services/index.d.ts +2 -0
  9. package/dist/cjs/services/parameter-service.d.ts +43 -0
  10. package/dist/cjs/tools/entity-resolver-tool.d.ts +5 -3
  11. package/dist/esm/index.js +9 -5
  12. package/dist/esm/index.js.map +1 -1
  13. package/dist/esm/index10.js +2 -2
  14. package/dist/esm/index18.js +64 -17
  15. package/dist/esm/index18.js.map +1 -1
  16. package/dist/esm/index21.js +1 -1
  17. package/dist/esm/index23.js +3 -3
  18. package/dist/esm/index24.js +20 -4
  19. package/dist/esm/index24.js.map +1 -1
  20. package/dist/esm/index29.js +248 -903
  21. package/dist/esm/index29.js.map +1 -1
  22. package/dist/esm/index30.js +98 -219
  23. package/dist/esm/index30.js.map +1 -1
  24. package/dist/esm/index31.js +833 -1085
  25. package/dist/esm/index31.js.map +1 -1
  26. package/dist/esm/index32.js +228 -115
  27. package/dist/esm/index32.js.map +1 -1
  28. package/dist/esm/index33.js +1197 -79
  29. package/dist/esm/index33.js.map +1 -1
  30. package/dist/esm/index34.js +119 -39
  31. package/dist/esm/index34.js.map +1 -1
  32. package/dist/esm/index35.js +103 -96
  33. package/dist/esm/index35.js.map +1 -1
  34. package/dist/esm/index36.js +46 -21
  35. package/dist/esm/index36.js.map +1 -1
  36. package/dist/esm/index37.js +107 -12
  37. package/dist/esm/index37.js.map +1 -1
  38. package/dist/esm/index38.js +21 -7
  39. package/dist/esm/index38.js.map +1 -1
  40. package/dist/esm/index39.js +11 -26
  41. package/dist/esm/index39.js.map +1 -1
  42. package/dist/esm/index40.js +6 -4
  43. package/dist/esm/index40.js.map +1 -1
  44. package/dist/esm/index41.js +5 -255
  45. package/dist/esm/index41.js.map +1 -1
  46. package/dist/esm/index42.js +213 -142
  47. package/dist/esm/index42.js.map +1 -1
  48. package/dist/esm/index43.js +174 -82
  49. package/dist/esm/index43.js.map +1 -1
  50. package/dist/esm/index44.js +95 -0
  51. package/dist/esm/index44.js.map +1 -0
  52. package/dist/esm/index45.js +30 -0
  53. package/dist/esm/index45.js.map +1 -0
  54. package/dist/esm/index5.js +2 -2
  55. package/dist/esm/index6.js +76 -6
  56. package/dist/esm/index6.js.map +1 -1
  57. package/dist/esm/index8.js +1 -1
  58. package/dist/types/conversational-agent.d.ts +11 -1
  59. package/dist/types/memory/smart-memory-manager.d.ts +7 -1
  60. package/dist/types/services/attachment-processor.d.ts +41 -0
  61. package/dist/types/services/index.d.ts +2 -0
  62. package/dist/types/services/parameter-service.d.ts +43 -0
  63. package/dist/types/tools/entity-resolver-tool.d.ts +5 -3
  64. package/package.json +2 -1
  65. package/src/conversational-agent.ts +97 -5
  66. package/src/langchain/form-aware-agent-executor.ts +1 -1
  67. package/src/langchain/langchain-agent.ts +36 -18
  68. package/src/memory/smart-memory-manager.ts +80 -27
  69. package/src/scripts/test-inscribe-form-generation.ts +3 -3
  70. package/src/scripts/test-inscribe-wrapper-verification.ts +3 -3
  71. package/src/services/attachment-processor.ts +163 -0
  72. package/src/services/content-store-manager.ts +32 -4
  73. package/src/services/index.ts +2 -0
  74. package/src/services/parameter-service.ts +430 -0
  75. package/src/tools/entity-resolver-tool.ts +12 -18
@@ -1 +1 @@
1
- {"version":3,"file":"index6.js","sources":["../../src/conversational-agent.ts"],"sourcesContent":["import {\n ServerSigner,\n getAllHederaCorePlugins,\n BasePlugin,\n} from 'hedera-agent-kit';\nimport { Logger, type NetworkType } from '@hashgraphonline/standards-sdk';\nimport { createAgent } from './agent-factory';\nimport { LangChainProvider } from './providers';\nimport type { ChatResponse, ConversationContext } from './base-agent';\nimport { ChatOpenAI } from '@langchain/openai';\nimport { ChatAnthropic } from '@langchain/anthropic';\nimport {\n HumanMessage,\n AIMessage,\n SystemMessage,\n} from '@langchain/core/messages';\nimport type { AgentOperationalMode, MirrorNodeConfig } from 'hedera-agent-kit';\nimport { HCS10Plugin } from './plugins/hcs-10/HCS10Plugin';\nimport { HCS2Plugin } from './plugins/hcs-2/HCS2Plugin';\nimport { InscribePlugin } from './plugins/inscribe/InscribePlugin';\nimport { HbarPlugin } from './plugins/hbar/HbarPlugin';\nimport { OpenConvaiState } from '@hashgraphonline/standards-agent-kit';\nimport type { IStateManager } from '@hashgraphonline/standards-agent-kit';\nimport { getSystemMessage } from './config/system-message';\nimport type { MCPServerConfig, MCPConnectionStatus } from './mcp/types';\nimport { ContentStoreManager } from './services/content-store-manager';\nimport { SmartMemoryManager, type SmartMemoryConfig } from './memory';\nimport {\n createEntityTools,\n ResolveEntitiesTool,\n ExtractEntitiesTool,\n} from './tools/entity-resolver-tool';\nimport type { FormSubmission } from './forms/types';\n\nexport type ToolDescriptor = {\n name: string;\n namespace?: string;\n};\n\nexport type ChatHistoryItem = {\n type: 'human' | 'ai' | 'system';\n content: string;\n};\n\nexport type AgentInstance = ReturnType<typeof createAgent>;\n\nexport type MirrorNetwork = 'testnet' | 'mainnet' | 'previewnet';\n\nconst DEFAULT_MODEL_NAME = 'gpt-4o';\nconst DEFAULT_TEMPERATURE = 0.1;\nconst DEFAULT_NETWORK = 'testnet';\nconst DEFAULT_OPERATIONAL_MODE: AgentOperationalMode = 'autonomous';\n\nexport interface ConversationalAgentOptions {\n accountId: string;\n privateKey: string;\n network?: NetworkType;\n openAIApiKey: string;\n openAIModelName?: string;\n llmProvider?: 'openai' | 'anthropic';\n verbose?: boolean;\n operationalMode?: AgentOperationalMode;\n userAccountId?: string;\n customSystemMessagePreamble?: string;\n customSystemMessagePostamble?: string;\n additionalPlugins?: BasePlugin[];\n stateManager?: IStateManager;\n scheduleUserTransactionsInBytesMode?: boolean;\n mirrorNodeConfig?: MirrorNodeConfig;\n disableLogging?: boolean;\n enabledPlugins?: string[];\n toolFilter?: (tool: { name: string; namespace?: string }) => boolean;\n mcpServers?: MCPServerConfig[];\n\n /** Enable automatic entity memory functionality (default: true) */\n entityMemoryEnabled?: boolean;\n\n /** Configuration for entity memory system */\n entityMemoryConfig?: SmartMemoryConfig;\n}\n\n/**\n * The ConversationalAgent class is an optional wrapper around the HederaConversationalAgent class,\n * which includes the OpenConvAIPlugin and the OpenConvaiState by default.\n * If you want to use a different plugin or state manager, you can pass them in the options.\n * This class is not required and the plugin can be used directly with the HederaConversationalAgent class.\n *\n * @param options - The options for the ConversationalAgent.\n * @returns A new instance of the ConversationalAgent class.\n */\nexport class ConversationalAgent {\n private static readonly NOT_INITIALIZED_ERROR =\n 'Agent not initialized. Call initialize() first.';\n protected agent?: AgentInstance;\n public hcs10Plugin: HCS10Plugin;\n public hcs2Plugin: HCS2Plugin;\n public inscribePlugin: InscribePlugin;\n public hbarPlugin: HbarPlugin;\n public stateManager: IStateManager;\n private options: ConversationalAgentOptions;\n public logger: Logger;\n public contentStoreManager?: ContentStoreManager;\n public memoryManager?: SmartMemoryManager | undefined;\n private entityTools?: {\n resolveEntities: ResolveEntitiesTool;\n extractEntities: ExtractEntitiesTool;\n };\n\n constructor(options: ConversationalAgentOptions) {\n this.options = options;\n this.stateManager = options.stateManager || new OpenConvaiState();\n this.hcs10Plugin = new HCS10Plugin();\n this.hcs2Plugin = new HCS2Plugin();\n this.inscribePlugin = new InscribePlugin();\n this.hbarPlugin = new HbarPlugin();\n this.logger = new Logger({\n module: 'ConversationalAgent',\n silent: options.disableLogging || false,\n });\n\n if (this.options.entityMemoryEnabled !== false) {\n if (!options.openAIApiKey) {\n throw new Error(\n 'OpenAI API key is required when entity memory is enabled'\n );\n }\n\n this.memoryManager = new SmartMemoryManager(\n this.options.entityMemoryConfig\n );\n this.logger.info('Entity memory initialized');\n\n this.entityTools = createEntityTools(options.openAIApiKey, 'gpt-4o-mini');\n this.logger.info('LLM-based entity resolver tools initialized');\n }\n }\n\n /**\n * Initialize the conversational agent with Hedera Hashgraph connection and AI configuration\n * @throws {Error} If account ID or private key is missing\n * @throws {Error} If initialization fails\n */\n async initialize(): Promise<void> {\n const {\n accountId,\n privateKey,\n network = DEFAULT_NETWORK,\n openAIApiKey,\n openAIModelName = DEFAULT_MODEL_NAME,\n llmProvider = 'openai',\n } = this.options;\n\n this.validateOptions(accountId, privateKey);\n\n try {\n const serverSigner = new ServerSigner(\n accountId!,\n privateKey!,\n network as MirrorNetwork\n );\n\n let llm: ChatOpenAI | ChatAnthropic;\n if (llmProvider === 'anthropic') {\n llm = new ChatAnthropic({\n apiKey: openAIApiKey,\n modelName: openAIModelName || 'claude-3-5-sonnet-20241022',\n temperature: DEFAULT_TEMPERATURE,\n });\n } else {\n const modelName = openAIModelName || 'gpt-4o-mini';\n const isGPT5Model =\n modelName.toLowerCase().includes('gpt-5') ||\n modelName.toLowerCase().includes('gpt5');\n llm = new ChatOpenAI({\n apiKey: openAIApiKey,\n modelName: openAIModelName,\n ...(isGPT5Model\n ? { temperature: 1 }\n : { temperature: DEFAULT_TEMPERATURE }),\n });\n }\n\n this.logger.info('Preparing plugins...');\n const allPlugins = this.preparePlugins();\n this.logger.info('Creating agent config...');\n const agentConfig = this.createAgentConfig(serverSigner, llm, allPlugins);\n\n this.logger.info('Creating agent...');\n this.agent = createAgent(agentConfig);\n this.logger.info('Agent created');\n\n this.logger.info('Configuring HCS10 plugin...');\n this.configureHCS10Plugin(allPlugins);\n this.logger.info('HCS10 plugin configured');\n\n this.contentStoreManager = new ContentStoreManager();\n await this.contentStoreManager.initialize();\n this.logger.info(\n 'ContentStoreManager initialized for content reference support'\n );\n\n this.logger.info('About to call agent.boot()');\n this.logger.info('🔥 About to call agent.boot()');\n await this.agent.boot();\n this.logger.info('agent.boot() completed');\n this.logger.info('🔥 agent.boot() completed');\n\n if (this.agent) {\n const cfg = agentConfig;\n cfg.filtering = cfg.filtering || {};\n const originalPredicate = cfg.filtering.toolPredicate as\n | ((t: ToolDescriptor) => boolean)\n | undefined;\n const userPredicate = this.options.toolFilter;\n cfg.filtering.toolPredicate = (tool: ToolDescriptor): boolean => {\n if (tool && tool.name === 'hedera-account-transfer-hbar') {\n return false;\n }\n if (tool && tool.name === 'hedera-hts-airdrop-token') {\n return false;\n }\n if (originalPredicate && !originalPredicate(tool)) {\n return false;\n }\n if (userPredicate && !userPredicate(tool)) {\n return false;\n }\n return true;\n };\n }\n\n if (this.options.mcpServers && this.options.mcpServers.length > 0) {\n this.connectMCP();\n }\n } catch (error) {\n this.logger.error('Failed to initialize ConversationalAgent:', error);\n throw error;\n }\n }\n\n /**\n * Get the HCS-10 plugin instance\n * @returns {HCS10Plugin} The HCS-10 plugin instance\n */\n getPlugin(): HCS10Plugin {\n return this.hcs10Plugin;\n }\n\n /**\n * Get the state manager instance\n * @returns {IStateManager} The state manager instance\n */\n getStateManager(): IStateManager {\n return this.stateManager;\n }\n\n /**\n * Get the underlying agent instance\n * @returns {ReturnType<typeof createAgent>} The agent instance\n * @throws {Error} If agent is not initialized\n */\n getAgent(): ReturnType<typeof createAgent> {\n if (!this.agent) {\n throw new Error(ConversationalAgent.NOT_INITIALIZED_ERROR);\n }\n return this.agent;\n }\n\n /**\n * Get the conversational agent instance (alias for getAgent)\n * @returns {ReturnType<typeof createAgent>} The agent instance\n * @throws {Error} If agent is not initialized\n */\n getConversationalAgent(): ReturnType<typeof createAgent> {\n return this.getAgent();\n }\n\n /**\n * Process a message through the conversational agent\n * @param {string} message - The message to process\n * @param {Array<{type: 'human' | 'ai'; content: string}>} chatHistory - Previous chat history\n * @returns {Promise<ChatResponse>} The agent's response\n * @throws {Error} If agent is not initialized\n */\n async processMessage(\n message: string,\n chatHistory: ChatHistoryItem[] = []\n ): Promise<ChatResponse> {\n if (!this.agent) {\n throw new Error('Agent not initialized. Call initialize() first.');\n }\n\n try {\n const resolvedMessage = message;\n\n const messages = chatHistory.map((msg) => {\n const content = msg.content;\n if (msg.type === 'system') {\n return new SystemMessage(content);\n }\n return msg.type === 'human'\n ? new HumanMessage(content)\n : new AIMessage(content);\n });\n\n const context: ConversationContext = { messages };\n const response = await this.agent.chat(resolvedMessage, context);\n\n if (\n this.memoryManager &&\n this.options.operationalMode !== 'returnBytes'\n ) {\n await this.extractAndStoreEntities(response, message);\n }\n\n this.logger.info('Message processed successfully');\n return response;\n } catch (error) {\n this.logger.error('Error processing message:', error);\n throw error;\n }\n }\n\n /**\n * Process form submission through the conversational agent\n * @param {FormSubmission} submission - The form submission data\n * @returns {Promise<ChatResponse>} The agent's response after processing the form\n * @throws {Error} If agent is not initialized or doesn't support form processing\n */\n async processFormSubmission(\n submission: FormSubmission\n ): Promise<ChatResponse> {\n if (!this.agent) {\n throw new Error(ConversationalAgent.NOT_INITIALIZED_ERROR);\n }\n\n try {\n this.logger.info('Processing form submission:', {\n formId: submission.formId,\n toolName: submission.toolName,\n parameterKeys: Object.keys(submission.parameters || {}),\n hasContext: !!submission.context,\n });\n const response = await this.agent.processFormSubmission(submission);\n this.logger.info('Form submission processed successfully');\n return response;\n } catch (error) {\n this.logger.error('Error processing form submission:', error);\n throw error;\n }\n }\n\n /**\n * Validates initialization options and throws if required fields are missing.\n *\n * @param accountId - The Hedera account ID\n * @param privateKey - The private key for the account\n * @throws {Error} If required fields are missing\n */\n private validateOptions(accountId?: string, privateKey?: string): void {\n if (!accountId || !privateKey) {\n throw new Error('Account ID and private key are required');\n }\n\n if (typeof accountId !== 'string') {\n throw new Error(\n `Account ID must be a string, received ${typeof accountId}`\n );\n }\n\n if (typeof privateKey !== 'string') {\n throw new Error(\n `Private key must be a string, received ${typeof privateKey}: ${JSON.stringify(\n privateKey\n )}`\n );\n }\n\n if (privateKey.length < 10) {\n throw new Error('Private key appears to be invalid (too short)');\n }\n }\n\n /**\n * Prepares the list of plugins to use based on configuration.\n *\n * @returns Array of plugins to initialize with the agent\n */\n private preparePlugins(): BasePlugin[] {\n const { additionalPlugins = [], enabledPlugins } = this.options;\n\n const standardPlugins = [\n this.hcs10Plugin,\n this.hcs2Plugin,\n this.inscribePlugin,\n this.hbarPlugin,\n ];\n\n const corePlugins = getAllHederaCorePlugins();\n\n if (enabledPlugins) {\n const enabledSet = new Set(enabledPlugins);\n const filteredPlugins = [...standardPlugins, ...corePlugins].filter(\n (plugin) => enabledSet.has(plugin.id)\n );\n return [...filteredPlugins, ...additionalPlugins];\n }\n\n return [...standardPlugins, ...corePlugins, ...additionalPlugins];\n }\n\n /**\n * Creates the agent configuration object.\n *\n * @param serverSigner - The server signer instance\n * @param llm - The language model instance\n * @param allPlugins - Array of plugins to use\n * @returns Configuration object for creating the agent\n */\n private createAgentConfig(\n serverSigner: ServerSigner,\n llm: ChatOpenAI | ChatAnthropic,\n allPlugins: BasePlugin[]\n ): Parameters<typeof createAgent>[0] {\n const {\n operationalMode = DEFAULT_OPERATIONAL_MODE,\n userAccountId,\n scheduleUserTransactionsInBytesMode,\n customSystemMessagePreamble,\n customSystemMessagePostamble,\n verbose = false,\n mirrorNodeConfig,\n disableLogging,\n accountId = '',\n } = this.options;\n\n return {\n framework: 'langchain',\n signer: serverSigner,\n execution: {\n mode: operationalMode === 'autonomous' ? 'direct' : 'bytes',\n operationalMode: operationalMode,\n ...(userAccountId && { userAccountId }),\n ...(scheduleUserTransactionsInBytesMode !== undefined && {\n scheduleUserTransactionsInBytesMode:\n scheduleUserTransactionsInBytesMode,\n scheduleUserTransactions: scheduleUserTransactionsInBytesMode,\n }),\n },\n ai: {\n provider: new LangChainProvider(llm),\n temperature: DEFAULT_TEMPERATURE,\n },\n filtering: {\n toolPredicate: (tool: ToolDescriptor): boolean => {\n if (tool.name === 'hedera-account-transfer-hbar') return false;\n if (this.options.toolFilter && !this.options.toolFilter(tool)) {\n return false;\n }\n return true;\n },\n },\n messaging: {\n systemPreamble:\n customSystemMessagePreamble || getSystemMessage(accountId),\n ...(customSystemMessagePostamble && {\n systemPostamble: customSystemMessagePostamble,\n }),\n conciseMode: true,\n },\n extensions: {\n plugins: allPlugins,\n ...(mirrorNodeConfig && {\n mirrorConfig: mirrorNodeConfig as Record<string, unknown>,\n }),\n },\n ...(this.options.mcpServers && {\n mcp: {\n servers: this.options.mcpServers,\n autoConnect: false,\n },\n }),\n debug: {\n verbose,\n silent: disableLogging ?? false,\n },\n };\n }\n\n /**\n * Configures the HCS-10 plugin with the state manager.\n *\n * @param allPlugins - Array of all plugins\n */\n private configureHCS10Plugin(allPlugins: BasePlugin[]): void {\n const hcs10 = allPlugins.find((p) => p.id === 'hcs-10');\n if (hcs10) {\n (\n hcs10 as BasePlugin & { appConfig?: Record<string, unknown> }\n ).appConfig = {\n stateManager: this.stateManager,\n };\n }\n }\n\n /**\n * Create a ConversationalAgent with specific plugins enabled\n */\n private static withPlugins(\n options: ConversationalAgentOptions,\n plugins: string[]\n ): ConversationalAgent {\n return new ConversationalAgent({\n ...options,\n enabledPlugins: plugins,\n });\n }\n\n /**\n * Create a ConversationalAgent with only HTS (Hedera Token Service) tools enabled\n */\n static withHTS(options: ConversationalAgentOptions): ConversationalAgent {\n return this.withPlugins(options, ['hts-token']);\n }\n\n /**\n * Create a ConversationalAgent with only HCS-2 tools enabled\n */\n static withHCS2(options: ConversationalAgentOptions): ConversationalAgent {\n return this.withPlugins(options, ['hcs-2']);\n }\n\n /**\n * Create a ConversationalAgent with only HCS-10 tools enabled\n */\n static withHCS10(options: ConversationalAgentOptions): ConversationalAgent {\n return this.withPlugins(options, ['hcs-10']);\n }\n\n /**\n * Create a ConversationalAgent with only inscription tools enabled\n */\n static withInscribe(\n options: ConversationalAgentOptions\n ): ConversationalAgent {\n return this.withPlugins(options, ['inscribe']);\n }\n\n /**\n * Create a ConversationalAgent with only account management tools enabled\n */\n static withAccount(options: ConversationalAgentOptions): ConversationalAgent {\n return this.withPlugins(options, ['account']);\n }\n\n /**\n * Create a ConversationalAgent with only file service tools enabled\n */\n static withFileService(\n options: ConversationalAgentOptions\n ): ConversationalAgent {\n return this.withPlugins(options, ['file-service']);\n }\n\n /**\n * Create a ConversationalAgent with only consensus service tools enabled\n */\n static withConsensusService(\n options: ConversationalAgentOptions\n ): ConversationalAgent {\n return this.withPlugins(options, ['consensus-service']);\n }\n\n /**\n * Create a ConversationalAgent with only smart contract tools enabled\n */\n static withSmartContract(\n options: ConversationalAgentOptions\n ): ConversationalAgent {\n return this.withPlugins(options, ['smart-contract']);\n }\n\n /**\n * Create a ConversationalAgent with all HCS standards plugins\n */\n static withAllStandards(\n options: ConversationalAgentOptions\n ): ConversationalAgent {\n return this.withPlugins(options, ['hcs-10', 'hcs-2', 'inscribe']);\n }\n\n /**\n * Create a ConversationalAgent with minimal Hedera tools (no HCS standards)\n */\n static minimal(options: ConversationalAgentOptions): ConversationalAgent {\n return this.withPlugins(options, []);\n }\n\n /**\n * Create a ConversationalAgent with MCP servers configured\n */\n static withMCP(\n options: ConversationalAgentOptions,\n mcpServers: MCPServerConfig[]\n ): ConversationalAgent {\n return new ConversationalAgent({\n ...options,\n mcpServers,\n });\n }\n\n /**\n * Extract and store entities from agent responses\n * @param response - Agent response containing potential entity information\n * @param originalMessage - Original user message for context\n */\n private async extractAndStoreEntities(\n response: unknown,\n originalMessage: string\n ): Promise<void> {\n if (!this.memoryManager || !this.entityTools) {\n return;\n }\n\n try {\n this.logger.info('Starting LLM-based entity extraction');\n\n const responseText = this.extractResponseText(response);\n\n const entitiesJson = await this.entityTools.extractEntities.call({\n response: responseText,\n userMessage: originalMessage,\n });\n\n try {\n const entities = JSON.parse(entitiesJson);\n\n for (const entity of entities) {\n if (\n entity &&\n typeof entity === 'object' &&\n 'name' in entity &&\n 'type' in entity &&\n 'id' in entity\n ) {\n this.logger.info(\n `Storing entity: ${entity.name} (${entity.type}) -> ${entity.id}`\n );\n\n const transactionId = this.extractTransactionId(response);\n const idStr = String(entity.id);\n const isHederaId = /^0\\.0\\.[0-9]+$/.test(idStr);\n if (!isHederaId) {\n this.logger.warn('Skipping non-ID entity from extraction', {\n id: idStr,\n name: String(entity.name),\n type: String(entity.type),\n });\n } else {\n this.memoryManager.storeEntityAssociation(\n idStr,\n String(entity.name),\n String(entity.type),\n transactionId\n );\n }\n }\n }\n\n if (entities.length > 0) {\n this.logger.info(\n `Stored ${entities.length} entities via LLM extraction`\n );\n } else {\n this.logger.info('No entities found in response via LLM extraction');\n }\n } catch (parseError) {\n this.logger.error(\n 'Failed to parse extracted entities JSON:',\n parseError\n );\n throw parseError;\n }\n } catch (error) {\n this.logger.error('Entity extraction failed:', error);\n throw error;\n }\n }\n\n /**\n * Extract transaction ID from response if available\n * @param response - Transaction response\n * @returns Transaction ID or undefined\n */\n private extractTransactionId(response: unknown): string | undefined {\n try {\n if (\n typeof response === 'object' &&\n response &&\n 'transactionId' in response\n ) {\n const responseWithTxId = response as { transactionId?: unknown };\n return typeof responseWithTxId.transactionId === 'string'\n ? responseWithTxId.transactionId\n : undefined;\n }\n if (typeof response === 'string') {\n const match = response.match(\n /transaction[\\s\\w]*ID[\\s:\"]*([0-9a-fA-F@\\.\\-]+)/i\n );\n return match ? match[1] : undefined;\n }\n return undefined;\n } catch {\n return undefined;\n }\n }\n\n /**\n * Connect to MCP servers asynchronously\n * @private\n */\n private connectMCP(): void {\n if (!this.agent || !this.options.mcpServers) {\n return;\n }\n\n this.agent\n .connectMCPServers()\n .catch((e) => {\n this.logger.error('Failed to connect MCP servers:', e);\n })\n .then(() => {\n this.logger.info('MCP servers connected successfully');\n });\n }\n\n /**\n * Get MCP connection status for all servers\n * @returns {Map<string, MCPConnectionStatus>} Connection status map\n */\n getMCPConnectionStatus(): Map<string, MCPConnectionStatus> {\n if (this.agent) {\n return this.agent.getMCPConnectionStatus();\n }\n return new Map();\n }\n\n /**\n * Check if a specific MCP server is connected\n * @param {string} serverName - Name of the server to check\n * @returns {boolean} True if connected, false otherwise\n */\n isMCPServerConnected(serverName: string): boolean {\n if (this.agent) {\n const statusMap = this.agent.getMCPConnectionStatus();\n const status = statusMap.get(serverName);\n return status?.connected ?? false;\n }\n return false;\n }\n\n /**\n * Clean up resources\n */\n async cleanup(): Promise<void> {\n try {\n this.logger.info('Cleaning up ConversationalAgent...');\n\n if (this.memoryManager) {\n try {\n this.memoryManager.dispose();\n this.logger.info('Memory manager cleaned up successfully');\n } catch (error) {\n this.logger.warn('Error cleaning up memory manager:', error);\n }\n this.memoryManager = undefined;\n }\n\n if (this.contentStoreManager) {\n await this.contentStoreManager.dispose();\n this.logger.info('ContentStoreManager cleaned up');\n }\n\n this.logger.info('ConversationalAgent cleanup completed');\n } catch (error) {\n this.logger.error('Error during cleanup:', error);\n }\n }\n\n private extractResponseText(response: unknown): string {\n if (typeof response === 'string') {\n return response;\n }\n\n if (response && typeof response === 'object' && 'output' in response) {\n const responseWithOutput = response as { output: unknown };\n return String(responseWithOutput.output);\n }\n\n return JSON.stringify(response);\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index6.js","sources":["../../src/conversational-agent.ts"],"sourcesContent":["import {\n ServerSigner,\n getAllHederaCorePlugins,\n BasePlugin,\n} from 'hedera-agent-kit';\nimport { Logger, type NetworkType } from '@hashgraphonline/standards-sdk';\nimport { createAgent } from './agent-factory';\nimport { LangChainProvider } from './providers';\nimport type { ChatResponse, ConversationContext } from './base-agent';\nimport { ChatOpenAI } from '@langchain/openai';\nimport OpenAI from 'openai';\nimport { ChatAnthropic } from '@langchain/anthropic';\nimport {\n HumanMessage,\n AIMessage,\n SystemMessage,\n} from '@langchain/core/messages';\nimport type { AgentOperationalMode, MirrorNodeConfig } from 'hedera-agent-kit';\nimport { HCS10Plugin } from './plugins/hcs-10/HCS10Plugin';\nimport { HCS2Plugin } from './plugins/hcs-2/HCS2Plugin';\nimport { InscribePlugin } from './plugins/inscribe/InscribePlugin';\nimport { HbarPlugin } from './plugins/hbar/HbarPlugin';\nimport { OpenConvaiState } from '@hashgraphonline/standards-agent-kit';\nimport type { IStateManager } from '@hashgraphonline/standards-agent-kit';\nimport { getSystemMessage } from './config/system-message';\nimport type { MCPServerConfig, MCPConnectionStatus } from './mcp/types';\nimport { ContentStoreManager } from './services/content-store-manager';\nimport { SmartMemoryManager, type SmartMemoryConfig } from './memory';\nimport {\n createEntityTools,\n ResolveEntitiesTool,\n ExtractEntitiesTool,\n} from './tools/entity-resolver-tool';\nimport type { FormSubmission } from './forms/types';\n\nexport type ToolDescriptor = {\n name: string;\n namespace?: string;\n};\n\nexport type ChatHistoryItem = {\n type: 'human' | 'ai' | 'system';\n content: string;\n};\n\nexport type AgentInstance = ReturnType<typeof createAgent>;\n\nexport type MirrorNetwork = 'testnet' | 'mainnet' | 'previewnet';\n\nconst DEFAULT_MODEL_NAME = 'gpt-4o';\nconst DEFAULT_TEMPERATURE = 0.1;\nconst DEFAULT_NETWORK = 'testnet';\nconst DEFAULT_OPERATIONAL_MODE: AgentOperationalMode = 'autonomous';\n\nexport interface ConversationalAgentOptions {\n accountId: string;\n privateKey: string;\n network?: NetworkType;\n openAIApiKey: string;\n openAIModelName?: string;\n llmProvider?: 'openai' | 'anthropic' | 'openrouter';\n verbose?: boolean;\n operationalMode?: AgentOperationalMode;\n userAccountId?: string;\n customSystemMessagePreamble?: string;\n customSystemMessagePostamble?: string;\n additionalPlugins?: BasePlugin[];\n stateManager?: IStateManager;\n scheduleUserTransactionsInBytesMode?: boolean;\n mirrorNodeConfig?: MirrorNodeConfig;\n disableLogging?: boolean;\n enabledPlugins?: string[];\n toolFilter?: (tool: { name: string; namespace?: string }) => boolean;\n mcpServers?: MCPServerConfig[];\n\n /** Enable automatic entity memory functionality (default: true) */\n entityMemoryEnabled?: boolean;\n\n /** Configuration for entity memory system */\n entityMemoryConfig?: SmartMemoryConfig;\n\n /**\n * Provider used for entity extraction/resolution tools (defaults to llmProvider or 'openai')\n */\n entityMemoryProvider?: 'openai' | 'anthropic' | 'openrouter';\n\n /**\n * Model name for entity extraction/resolution tools (defaults per provider)\n */\n entityMemoryModelName?: string;\n\n openRouterApiKey?: string;\n openRouterBaseURL?: string;\n}\n\n/**\n * The ConversationalAgent class is an optional wrapper around the HederaConversationalAgent class,\n * which includes the OpenConvAIPlugin and the OpenConvaiState by default.\n * If you want to use a different plugin or state manager, you can pass them in the options.\n * This class is not required and the plugin can be used directly with the HederaConversationalAgent class.\n *\n * @param options - The options for the ConversationalAgent.\n * @returns A new instance of the ConversationalAgent class.\n */\nexport class ConversationalAgent {\n private static readonly NOT_INITIALIZED_ERROR =\n 'Agent not initialized. Call initialize() first.';\n protected agent?: AgentInstance;\n public hcs10Plugin: HCS10Plugin;\n public hcs2Plugin: HCS2Plugin;\n public inscribePlugin: InscribePlugin;\n public hbarPlugin: HbarPlugin;\n public stateManager: IStateManager;\n private options: ConversationalAgentOptions;\n public logger: Logger;\n public contentStoreManager?: ContentStoreManager;\n public memoryManager?: SmartMemoryManager | undefined;\n private entityTools?: {\n resolveEntities: ResolveEntitiesTool;\n extractEntities: ExtractEntitiesTool;\n };\n\n constructor(options: ConversationalAgentOptions) {\n this.options = options;\n this.stateManager = options.stateManager || new OpenConvaiState();\n this.hcs10Plugin = new HCS10Plugin();\n this.hcs2Plugin = new HCS2Plugin();\n this.inscribePlugin = new InscribePlugin();\n this.hbarPlugin = new HbarPlugin();\n this.logger = new Logger({\n module: 'ConversationalAgent',\n silent: options.disableLogging || false,\n });\n\n if (this.options.entityMemoryEnabled !== false) {\n if (!options.openAIApiKey) {\n throw new Error(\n 'OpenAI/Anthropic API key is required when entity memory is enabled'\n );\n }\n\n this.memoryManager = new SmartMemoryManager(\n this.options.entityMemoryConfig\n );\n this.logger.info('Entity memory initialized');\n\n const provider = options.entityMemoryProvider || options.llmProvider || 'openai';\n const modelName =\n options.entityMemoryModelName ||\n (provider === 'anthropic'\n ? 'claude-3-7-sonnet-latest'\n : provider === 'openrouter'\n ? 'openai/gpt-4o-mini'\n : 'gpt-4o-mini');\n\n let resolverLLM: ChatOpenAI | ChatAnthropic;\n if (provider === 'anthropic') {\n resolverLLM = new ChatAnthropic({\n apiKey: options.openAIApiKey,\n model: modelName,\n temperature: 0,\n });\n } else if (provider === 'openrouter') {\n const baseURL = options.openRouterBaseURL || 'https://openrouter.ai/api/v1';\n const apiKey = options.openRouterApiKey || options.openAIApiKey;\n const client = new OpenAI({\n apiKey,\n baseURL,\n defaultHeaders: {\n Referer: process.env.OPENROUTER_REFERRER || 'https://hashgraphonline.com',\n 'HTTP-Referer': process.env.OPENROUTER_REFERRER || 'https://hashgraphonline.com',\n 'X-Title': process.env.OPENROUTER_TITLE || 'Hashgraph Online Conversational Agent',\n },\n });\n resolverLLM = new ChatOpenAI({\n client,\n model: modelName,\n temperature: 0,\n });\n } else {\n resolverLLM = new ChatOpenAI({\n apiKey: options.openAIApiKey,\n model: modelName,\n temperature: 0,\n });\n }\n\n this.entityTools = createEntityTools(resolverLLM);\n this.logger.info('LLM-based entity resolver tools initialized');\n }\n }\n\n /**\n * Initialize the conversational agent with Hedera Hashgraph connection and AI configuration\n * @throws {Error} If account ID or private key is missing\n * @throws {Error} If initialization fails\n */\n async initialize(): Promise<void> {\n const {\n accountId,\n privateKey,\n network = DEFAULT_NETWORK,\n openAIApiKey,\n openAIModelName = DEFAULT_MODEL_NAME,\n llmProvider = 'openai',\n } = this.options;\n\n this.validateOptions(accountId, privateKey);\n\n try {\n const serverSigner = new ServerSigner(\n accountId!,\n privateKey!,\n network as MirrorNetwork\n );\n\n let llm: ChatOpenAI | ChatAnthropic;\n let providerInfo: Record<string, unknown> = { provider: llmProvider };\n if (llmProvider === 'anthropic') {\n llm = new ChatAnthropic({\n apiKey: openAIApiKey,\n model: openAIModelName || 'claude-3-7-sonnet-latest',\n temperature: DEFAULT_TEMPERATURE,\n });\n providerInfo = {\n ...providerInfo,\n model: openAIModelName || 'claude-3-7-sonnet-latest',\n keyPresent: !!openAIApiKey,\n };\n } else if (llmProvider === 'openrouter') {\n const baseURL = this.options.openRouterBaseURL || 'https://openrouter.ai/api/v1';\n const apiKey = this.options.openRouterApiKey || openAIApiKey;\n const modelName = openAIModelName || 'anthropic/claude-3-haiku-20240307';\n const client = new OpenAI({\n apiKey,\n baseURL,\n defaultHeaders: {\n Referer: process.env.OPENROUTER_REFERRER || 'https://hashgraphonline.com',\n 'HTTP-Referer': process.env.OPENROUTER_REFERRER || 'https://hashgraphonline.com',\n 'X-Title': process.env.OPENROUTER_TITLE || 'Hashgraph Online Conversational Agent',\n },\n });\n llm = new ChatOpenAI({\n client,\n model: modelName,\n temperature: DEFAULT_TEMPERATURE,\n });\n providerInfo = {\n ...providerInfo,\n model: modelName,\n baseURL,\n keyPresent: !!apiKey,\n };\n } else {\n const modelName = openAIModelName || 'gpt-4o-mini';\n const isGPT5Model =\n modelName.toLowerCase().includes('gpt-5') ||\n modelName.toLowerCase().includes('gpt5');\n llm = new ChatOpenAI({\n apiKey: openAIApiKey,\n model: modelName,\n ...(isGPT5Model\n ? { temperature: 1 }\n : { temperature: DEFAULT_TEMPERATURE }),\n });\n providerInfo = {\n ...providerInfo,\n model: modelName,\n keyPresent: !!openAIApiKey,\n };\n }\n\n this.logger.info('AI provider configured', providerInfo);\n\n this.logger.info('Preparing plugins...');\n const allPlugins = this.preparePlugins();\n this.logger.info('Creating agent config...');\n const agentConfig = this.createAgentConfig(serverSigner, llm, allPlugins);\n\n this.logger.info('Creating agent...');\n this.agent = createAgent(agentConfig);\n this.logger.info('Agent created');\n\n this.logger.info('Configuring HCS10 plugin...');\n this.configureHCS10Plugin(allPlugins);\n this.logger.info('HCS10 plugin configured');\n\n this.contentStoreManager = new ContentStoreManager();\n await this.contentStoreManager.initialize();\n this.logger.info(\n 'ContentStoreManager initialized for content reference support'\n );\n\n this.logger.info('About to call agent.boot()');\n this.logger.info('🔥 About to call agent.boot()');\n await this.agent.boot();\n this.logger.info('agent.boot() completed');\n this.logger.info('🔥 agent.boot() completed');\n\n if (this.agent) {\n const cfg = agentConfig;\n cfg.filtering = cfg.filtering || {};\n const originalPredicate = cfg.filtering.toolPredicate as\n | ((t: ToolDescriptor) => boolean)\n | undefined;\n const userPredicate = this.options.toolFilter;\n cfg.filtering.toolPredicate = (tool: ToolDescriptor): boolean => {\n if (tool && tool.name === 'hedera-account-transfer-hbar') {\n return false;\n }\n if (tool && tool.name === 'hedera-hts-airdrop-token') {\n return false;\n }\n if (originalPredicate && !originalPredicate(tool)) {\n return false;\n }\n if (userPredicate && !userPredicate(tool)) {\n return false;\n }\n return true;\n };\n }\n\n if (this.options.mcpServers && this.options.mcpServers.length > 0) {\n this.connectMCP();\n }\n } catch (error) {\n this.logger.error('Failed to initialize ConversationalAgent:', error);\n throw error;\n }\n }\n\n /**\n * Get the HCS-10 plugin instance\n * @returns {HCS10Plugin} The HCS-10 plugin instance\n */\n getPlugin(): HCS10Plugin {\n return this.hcs10Plugin;\n }\n\n /**\n * Get the state manager instance\n * @returns {IStateManager} The state manager instance\n */\n getStateManager(): IStateManager {\n return this.stateManager;\n }\n\n /**\n * Get the underlying agent instance\n * @returns {ReturnType<typeof createAgent>} The agent instance\n * @throws {Error} If agent is not initialized\n */\n getAgent(): ReturnType<typeof createAgent> {\n if (!this.agent) {\n throw new Error(ConversationalAgent.NOT_INITIALIZED_ERROR);\n }\n return this.agent;\n }\n\n /**\n * Get the conversational agent instance (alias for getAgent)\n * @returns {ReturnType<typeof createAgent>} The agent instance\n * @throws {Error} If agent is not initialized\n */\n getConversationalAgent(): ReturnType<typeof createAgent> {\n return this.getAgent();\n }\n\n /**\n * Process a message through the conversational agent\n * @param {string} message - The message to process\n * @param {Array<{type: 'human' | 'ai'; content: string}>} chatHistory - Previous chat history\n * @returns {Promise<ChatResponse>} The agent's response\n * @throws {Error} If agent is not initialized\n */\n async processMessage(\n message: string,\n chatHistory: ChatHistoryItem[] = []\n ): Promise<ChatResponse> {\n if (!this.agent) {\n throw new Error('Agent not initialized. Call initialize() first.');\n }\n\n try {\n const resolvedMessage = message;\n\n const messages = chatHistory.map((msg) => {\n const content = msg.content;\n if (msg.type === 'system') {\n return new SystemMessage(content);\n }\n return msg.type === 'human'\n ? new HumanMessage(content)\n : new AIMessage(content);\n });\n\n const context: ConversationContext = { messages };\n const response = await this.agent.chat(resolvedMessage, context);\n\n if (\n this.memoryManager &&\n this.options.operationalMode !== 'returnBytes'\n ) {\n await this.extractAndStoreEntities(response, message);\n }\n\n this.logger.info('Message processed successfully');\n return response;\n } catch (error) {\n this.logger.error('Error processing message:', error);\n throw error;\n }\n }\n\n /**\n * Process form submission through the conversational agent\n * @param {FormSubmission} submission - The form submission data\n * @returns {Promise<ChatResponse>} The agent's response after processing the form\n * @throws {Error} If agent is not initialized or doesn't support form processing\n */\n async processFormSubmission(\n submission: FormSubmission\n ): Promise<ChatResponse> {\n if (!this.agent) {\n throw new Error(ConversationalAgent.NOT_INITIALIZED_ERROR);\n }\n\n try {\n this.logger.info('Processing form submission:', {\n formId: submission.formId,\n toolName: submission.toolName,\n parameterKeys: Object.keys(submission.parameters || {}),\n hasContext: !!submission.context,\n });\n const response = await this.agent.processFormSubmission(submission);\n this.logger.info('Form submission processed successfully');\n return response;\n } catch (error) {\n this.logger.error('Error processing form submission:', error);\n throw error;\n }\n }\n\n /**\n * Validates initialization options and throws if required fields are missing.\n *\n * @param accountId - The Hedera account ID\n * @param privateKey - The private key for the account\n * @throws {Error} If required fields are missing\n */\n private validateOptions(accountId?: string, privateKey?: string): void {\n if (!accountId || !privateKey) {\n throw new Error('Account ID and private key are required');\n }\n\n if (typeof accountId !== 'string') {\n throw new Error(\n `Account ID must be a string, received ${typeof accountId}`\n );\n }\n\n if (typeof privateKey !== 'string') {\n throw new Error(\n `Private key must be a string, received ${typeof privateKey}: ${JSON.stringify(\n privateKey\n )}`\n );\n }\n\n if (privateKey.length < 10) {\n throw new Error('Private key appears to be invalid (too short)');\n }\n }\n\n /**\n * Prepares the list of plugins to use based on configuration.\n *\n * @returns Array of plugins to initialize with the agent\n */\n private preparePlugins(): BasePlugin[] {\n const { additionalPlugins = [], enabledPlugins } = this.options;\n\n const standardPlugins = [\n this.hcs10Plugin,\n this.hcs2Plugin,\n this.inscribePlugin,\n this.hbarPlugin,\n ];\n\n const corePlugins = getAllHederaCorePlugins();\n\n if (enabledPlugins) {\n const enabledSet = new Set(enabledPlugins);\n const filteredPlugins = [...standardPlugins, ...corePlugins].filter(\n (plugin) => enabledSet.has(plugin.id)\n );\n return [...filteredPlugins, ...additionalPlugins];\n }\n\n return [...standardPlugins, ...corePlugins, ...additionalPlugins];\n }\n\n /**\n * Creates the agent configuration object.\n *\n * @param serverSigner - The server signer instance\n * @param llm - The language model instance\n * @param allPlugins - Array of plugins to use\n * @returns Configuration object for creating the agent\n */\n private createAgentConfig(\n serverSigner: ServerSigner,\n llm: ChatOpenAI | ChatAnthropic,\n allPlugins: BasePlugin[]\n ): Parameters<typeof createAgent>[0] {\n const {\n operationalMode = DEFAULT_OPERATIONAL_MODE,\n userAccountId,\n scheduleUserTransactionsInBytesMode,\n customSystemMessagePreamble,\n customSystemMessagePostamble,\n verbose = false,\n mirrorNodeConfig,\n disableLogging,\n accountId = '',\n } = this.options;\n\n return {\n framework: 'langchain',\n signer: serverSigner,\n execution: {\n mode: operationalMode === 'autonomous' ? 'direct' : 'bytes',\n operationalMode: operationalMode,\n ...(userAccountId && { userAccountId }),\n ...(scheduleUserTransactionsInBytesMode !== undefined && {\n scheduleUserTransactionsInBytesMode:\n scheduleUserTransactionsInBytesMode,\n scheduleUserTransactions: scheduleUserTransactionsInBytesMode,\n }),\n },\n ai: {\n provider: new LangChainProvider(llm),\n temperature: DEFAULT_TEMPERATURE,\n },\n filtering: {\n toolPredicate: (tool: ToolDescriptor): boolean => {\n if (tool.name === 'hedera-account-transfer-hbar') return false;\n if (this.options.toolFilter && !this.options.toolFilter(tool)) {\n return false;\n }\n return true;\n },\n },\n messaging: {\n systemPreamble:\n customSystemMessagePreamble || getSystemMessage(accountId),\n ...(customSystemMessagePostamble && {\n systemPostamble: customSystemMessagePostamble,\n }),\n conciseMode: true,\n },\n extensions: {\n plugins: allPlugins,\n ...(mirrorNodeConfig && {\n mirrorConfig: mirrorNodeConfig as Record<string, unknown>,\n }),\n },\n ...(this.options.mcpServers && {\n mcp: {\n servers: this.options.mcpServers,\n autoConnect: false,\n },\n }),\n debug: {\n verbose,\n silent: disableLogging ?? false,\n },\n };\n }\n\n /**\n * Configures the HCS-10 plugin with the state manager.\n *\n * @param allPlugins - Array of all plugins\n */\n private configureHCS10Plugin(allPlugins: BasePlugin[]): void {\n const hcs10 = allPlugins.find((p) => p.id === 'hcs-10');\n if (hcs10) {\n (\n hcs10 as BasePlugin & { appConfig?: Record<string, unknown> }\n ).appConfig = {\n stateManager: this.stateManager,\n };\n }\n }\n\n /**\n * Create a ConversationalAgent with specific plugins enabled\n */\n private static withPlugins(\n options: ConversationalAgentOptions,\n plugins: string[]\n ): ConversationalAgent {\n return new ConversationalAgent({\n ...options,\n enabledPlugins: plugins,\n });\n }\n\n /**\n * Create a ConversationalAgent with only HTS (Hedera Token Service) tools enabled\n */\n static withHTS(options: ConversationalAgentOptions): ConversationalAgent {\n return this.withPlugins(options, ['hts-token']);\n }\n\n /**\n * Create a ConversationalAgent with only HCS-2 tools enabled\n */\n static withHCS2(options: ConversationalAgentOptions): ConversationalAgent {\n return this.withPlugins(options, ['hcs-2']);\n }\n\n /**\n * Create a ConversationalAgent with only HCS-10 tools enabled\n */\n static withHCS10(options: ConversationalAgentOptions): ConversationalAgent {\n return this.withPlugins(options, ['hcs-10']);\n }\n\n /**\n * Create a ConversationalAgent with only inscription tools enabled\n */\n static withInscribe(\n options: ConversationalAgentOptions\n ): ConversationalAgent {\n return this.withPlugins(options, ['inscribe']);\n }\n\n /**\n * Create a ConversationalAgent with only account management tools enabled\n */\n static withAccount(options: ConversationalAgentOptions): ConversationalAgent {\n return this.withPlugins(options, ['account']);\n }\n\n /**\n * Create a ConversationalAgent with only file service tools enabled\n */\n static withFileService(\n options: ConversationalAgentOptions\n ): ConversationalAgent {\n return this.withPlugins(options, ['file-service']);\n }\n\n /**\n * Create a ConversationalAgent with only consensus service tools enabled\n */\n static withConsensusService(\n options: ConversationalAgentOptions\n ): ConversationalAgent {\n return this.withPlugins(options, ['consensus-service']);\n }\n\n /**\n * Create a ConversationalAgent with only smart contract tools enabled\n */\n static withSmartContract(\n options: ConversationalAgentOptions\n ): ConversationalAgent {\n return this.withPlugins(options, ['smart-contract']);\n }\n\n /**\n * Create a ConversationalAgent with all HCS standards plugins\n */\n static withAllStandards(\n options: ConversationalAgentOptions\n ): ConversationalAgent {\n return this.withPlugins(options, ['hcs-10', 'hcs-2', 'inscribe']);\n }\n\n /**\n * Create a ConversationalAgent with minimal Hedera tools (no HCS standards)\n */\n static minimal(options: ConversationalAgentOptions): ConversationalAgent {\n return this.withPlugins(options, []);\n }\n\n /**\n * Create a ConversationalAgent with MCP servers configured\n */\n static withMCP(\n options: ConversationalAgentOptions,\n mcpServers: MCPServerConfig[]\n ): ConversationalAgent {\n return new ConversationalAgent({\n ...options,\n mcpServers,\n });\n }\n\n /**\n * Extract and store entities from agent responses\n * @param response - Agent response containing potential entity information\n * @param originalMessage - Original user message for context\n */\n private async extractAndStoreEntities(\n response: unknown,\n originalMessage: string\n ): Promise<void> {\n if (!this.memoryManager || !this.entityTools) {\n return;\n }\n\n try {\n this.logger.info('Starting LLM-based entity extraction');\n\n const responseText = this.extractResponseText(response);\n\n const entitiesJson = await this.entityTools.extractEntities.call({\n response: responseText,\n userMessage: originalMessage,\n });\n\n try {\n const entities = JSON.parse(entitiesJson);\n\n for (const entity of entities) {\n if (\n entity &&\n typeof entity === 'object' &&\n 'name' in entity &&\n 'type' in entity &&\n 'id' in entity\n ) {\n this.logger.info(\n `Storing entity: ${entity.name} (${entity.type}) -> ${entity.id}`\n );\n\n const transactionId = this.extractTransactionId(response);\n const idStr = String(entity.id);\n const isHederaId = /^0\\.0\\.[0-9]+$/.test(idStr);\n if (!isHederaId) {\n this.logger.warn('Skipping non-ID entity from extraction', {\n id: idStr,\n name: String(entity.name),\n type: String(entity.type),\n });\n } else {\n this.memoryManager.storeEntityAssociation(\n idStr,\n String(entity.name),\n String(entity.type),\n transactionId\n );\n }\n }\n }\n\n if (entities.length > 0) {\n this.logger.info(\n `Stored ${entities.length} entities via LLM extraction`\n );\n } else {\n this.logger.info('No entities found in response via LLM extraction');\n }\n } catch (parseError) {\n this.logger.error(\n 'Failed to parse extracted entities JSON:',\n parseError\n );\n throw parseError;\n }\n } catch (error) {\n this.logger.error('Entity extraction failed:', error);\n throw error;\n }\n }\n\n /**\n * Extract transaction ID from response if available\n * @param response - Transaction response\n * @returns Transaction ID or undefined\n */\n private extractTransactionId(response: unknown): string | undefined {\n try {\n if (\n typeof response === 'object' &&\n response &&\n 'transactionId' in response\n ) {\n const responseWithTxId = response as { transactionId?: unknown };\n return typeof responseWithTxId.transactionId === 'string'\n ? responseWithTxId.transactionId\n : undefined;\n }\n if (typeof response === 'string') {\n const match = response.match(\n /transaction[\\s\\w]*ID[\\s:\"]*([0-9a-fA-F@\\.\\-]+)/i\n );\n return match ? match[1] : undefined;\n }\n return undefined;\n } catch {\n return undefined;\n }\n }\n\n /**\n * Connect to MCP servers asynchronously\n * @private\n */\n private connectMCP(): void {\n if (!this.agent || !this.options.mcpServers) {\n return;\n }\n\n this.agent\n .connectMCPServers()\n .catch((e) => {\n this.logger.error('Failed to connect MCP servers:', e);\n })\n .then(() => {\n this.logger.info('MCP servers connected successfully');\n });\n }\n\n /**\n * Get MCP connection status for all servers\n * @returns {Map<string, MCPConnectionStatus>} Connection status map\n */\n getMCPConnectionStatus(): Map<string, MCPConnectionStatus> {\n if (this.agent) {\n return this.agent.getMCPConnectionStatus();\n }\n return new Map();\n }\n\n /**\n * Check if a specific MCP server is connected\n * @param {string} serverName - Name of the server to check\n * @returns {boolean} True if connected, false otherwise\n */\n isMCPServerConnected(serverName: string): boolean {\n if (this.agent) {\n const statusMap = this.agent.getMCPConnectionStatus();\n const status = statusMap.get(serverName);\n return status?.connected ?? false;\n }\n return false;\n }\n\n /**\n * Clean up resources\n */\n async cleanup(): Promise<void> {\n try {\n this.logger.info('Cleaning up ConversationalAgent...');\n\n if (this.memoryManager) {\n try {\n this.memoryManager.dispose();\n this.logger.info('Memory manager cleaned up successfully');\n } catch (error) {\n this.logger.warn('Error cleaning up memory manager:', error);\n }\n this.memoryManager = undefined;\n }\n\n if (this.contentStoreManager) {\n await this.contentStoreManager.dispose();\n this.logger.info('ContentStoreManager cleaned up');\n }\n\n this.logger.info('ConversationalAgent cleanup completed');\n } catch (error) {\n this.logger.error('Error during cleanup:', error);\n }\n }\n\n private extractResponseText(response: unknown): string {\n if (typeof response === 'string') {\n return response;\n }\n\n if (response && typeof response === 'object' && 'output' in response) {\n const responseWithOutput = response as { output: unknown };\n return String(responseWithOutput.output);\n }\n\n return JSON.stringify(response);\n }\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;AAiDA,MAAM,qBAAqB;AAC3B,MAAM,sBAAsB;AAC5B,MAAM,kBAAkB;AACxB,MAAM,2BAAiD;AAoDhD,MAAM,uBAAN,MAAM,qBAAoB;AAAA,EAkB/B,YAAY,SAAqC;AAC/C,SAAK,UAAU;AACf,SAAK,eAAe,QAAQ,gBAAgB,IAAI,gBAAA;AAChD,SAAK,cAAc,IAAI,YAAA;AACvB,SAAK,aAAa,IAAI,WAAA;AACtB,SAAK,iBAAiB,IAAI,eAAA;AAC1B,SAAK,aAAa,IAAI,WAAA;AACtB,SAAK,SAAS,IAAI,OAAO;AAAA,MACvB,QAAQ;AAAA,MACR,QAAQ,QAAQ,kBAAkB;AAAA,IAAA,CACnC;AAED,QAAI,KAAK,QAAQ,wBAAwB,OAAO;AAC9C,UAAI,CAAC,QAAQ,cAAc;AACzB,cAAM,IAAI;AAAA,UACR;AAAA,QAAA;AAAA,MAEJ;AAEA,WAAK,gBAAgB,IAAI;AAAA,QACvB,KAAK,QAAQ;AAAA,MAAA;AAEf,WAAK,OAAO,KAAK,2BAA2B;AAE5C,YAAM,WAAW,QAAQ,wBAAwB,QAAQ,eAAe;AACxE,YAAM,YACJ,QAAQ,0BACP,aAAa,cACV,6BACA,aAAa,eACb,uBACA;AAEN,UAAI;AACJ,UAAI,aAAa,aAAa;AAC5B,sBAAc,IAAI,cAAc;AAAA,UAC9B,QAAQ,QAAQ;AAAA,UAChB,OAAO;AAAA,UACP,aAAa;AAAA,QAAA,CACd;AAAA,MACH,WAAW,aAAa,cAAc;AACpC,cAAM,UAAU,QAAQ,qBAAqB;AAC7C,cAAM,SAAS,QAAQ,oBAAoB,QAAQ;AACnD,cAAM,SAAS,IAAI,OAAO;AAAA,UACxB;AAAA,UACA;AAAA,UACA,gBAAgB;AAAA,YACd,SAAS,QAAQ,IAAI,uBAAuB;AAAA,YAC5C,gBAAgB,QAAQ,IAAI,uBAAuB;AAAA,YACnD,WAAW,QAAQ,IAAI,oBAAoB;AAAA,UAAA;AAAA,QAC7C,CACD;AACD,sBAAc,IAAI,WAAW;AAAA,UAC3B;AAAA,UACA,OAAO;AAAA,UACP,aAAa;AAAA,QAAA,CACd;AAAA,MACH,OAAO;AACL,sBAAc,IAAI,WAAW;AAAA,UAC3B,QAAQ,QAAQ;AAAA,UAChB,OAAO;AAAA,UACP,aAAa;AAAA,QAAA,CACd;AAAA,MACH;AAEA,WAAK,cAAc,kBAAkB,WAAW;AAChD,WAAK,OAAO,KAAK,6CAA6C;AAAA,IAChE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,aAA4B;AAChC,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA,UAAU;AAAA,MACV;AAAA,MACA,kBAAkB;AAAA,MAClB,cAAc;AAAA,IAAA,IACZ,KAAK;AAET,SAAK,gBAAgB,WAAW,UAAU;AAE1C,QAAI;AACF,YAAM,eAAe,IAAI;AAAA,QACvB;AAAA,QACA;AAAA,QACA;AAAA,MAAA;AAGF,UAAI;AACJ,UAAI,eAAwC,EAAE,UAAU,YAAA;AACxD,UAAI,gBAAgB,aAAa;AAC/B,cAAM,IAAI,cAAc;AAAA,UACtB,QAAQ;AAAA,UACR,OAAO,mBAAmB;AAAA,UAC1B,aAAa;AAAA,QAAA,CACd;AACD,uBAAe;AAAA,UACb,GAAG;AAAA,UACH,OAAO,mBAAmB;AAAA,UAC1B,YAAY,CAAC,CAAC;AAAA,QAAA;AAAA,MAElB,WAAW,gBAAgB,cAAc;AACvC,cAAM,UAAU,KAAK,QAAQ,qBAAqB;AAClD,cAAM,SAAS,KAAK,QAAQ,oBAAoB;AAChD,cAAM,YAAY,mBAAmB;AACrC,cAAM,SAAS,IAAI,OAAO;AAAA,UACxB;AAAA,UACA;AAAA,UACA,gBAAgB;AAAA,YACd,SAAS,QAAQ,IAAI,uBAAuB;AAAA,YAC5C,gBAAgB,QAAQ,IAAI,uBAAuB;AAAA,YACnD,WAAW,QAAQ,IAAI,oBAAoB;AAAA,UAAA;AAAA,QAC7C,CACD;AACD,cAAM,IAAI,WAAW;AAAA,UACnB;AAAA,UACA,OAAO;AAAA,UACP,aAAa;AAAA,QAAA,CACd;AACD,uBAAe;AAAA,UACb,GAAG;AAAA,UACH,OAAO;AAAA,UACP;AAAA,UACA,YAAY,CAAC,CAAC;AAAA,QAAA;AAAA,MAElB,OAAO;AACL,cAAM,YAAY,mBAAmB;AACrC,cAAM,cACJ,UAAU,YAAA,EAAc,SAAS,OAAO,KACxC,UAAU,cAAc,SAAS,MAAM;AACzC,cAAM,IAAI,WAAW;AAAA,UACnB,QAAQ;AAAA,UACR,OAAO;AAAA,UACP,GAAI,cACA,EAAE,aAAa,MACf,EAAE,aAAa,oBAAA;AAAA,QAAoB,CACxC;AACD,uBAAe;AAAA,UACb,GAAG;AAAA,UACH,OAAO;AAAA,UACP,YAAY,CAAC,CAAC;AAAA,QAAA;AAAA,MAElB;AAEA,WAAK,OAAO,KAAK,0BAA0B,YAAY;AAEvD,WAAK,OAAO,KAAK,sBAAsB;AACvC,YAAM,aAAa,KAAK,eAAA;AACxB,WAAK,OAAO,KAAK,0BAA0B;AAC3C,YAAM,cAAc,KAAK,kBAAkB,cAAc,KAAK,UAAU;AAExE,WAAK,OAAO,KAAK,mBAAmB;AACpC,WAAK,QAAQ,YAAY,WAAW;AACpC,WAAK,OAAO,KAAK,eAAe;AAEhC,WAAK,OAAO,KAAK,6BAA6B;AAC9C,WAAK,qBAAqB,UAAU;AACpC,WAAK,OAAO,KAAK,yBAAyB;AAE1C,WAAK,sBAAsB,IAAI,oBAAA;AAC/B,YAAM,KAAK,oBAAoB,WAAA;AAC/B,WAAK,OAAO;AAAA,QACV;AAAA,MAAA;AAGF,WAAK,OAAO,KAAK,4BAA4B;AAC7C,WAAK,OAAO,KAAK,+BAA+B;AAChD,YAAM,KAAK,MAAM,KAAA;AACjB,WAAK,OAAO,KAAK,wBAAwB;AACzC,WAAK,OAAO,KAAK,2BAA2B;AAE5C,UAAI,KAAK,OAAO;AACd,cAAM,MAAM;AACZ,YAAI,YAAY,IAAI,aAAa,CAAA;AACjC,cAAM,oBAAoB,IAAI,UAAU;AAGxC,cAAM,gBAAgB,KAAK,QAAQ;AACnC,YAAI,UAAU,gBAAgB,CAAC,SAAkC;AAC/D,cAAI,QAAQ,KAAK,SAAS,gCAAgC;AACxD,mBAAO;AAAA,UACT;AACA,cAAI,QAAQ,KAAK,SAAS,4BAA4B;AACpD,mBAAO;AAAA,UACT;AACA,cAAI,qBAAqB,CAAC,kBAAkB,IAAI,GAAG;AACjD,mBAAO;AAAA,UACT;AACA,cAAI,iBAAiB,CAAC,cAAc,IAAI,GAAG;AACzC,mBAAO;AAAA,UACT;AACA,iBAAO;AAAA,QACT;AAAA,MACF;AAEA,UAAI,KAAK,QAAQ,cAAc,KAAK,QAAQ,WAAW,SAAS,GAAG;AACjE,aAAK,WAAA;AAAA,MACP;AAAA,IACF,SAAS,OAAO;AACd,WAAK,OAAO,MAAM,6CAA6C,KAAK;AACpE,YAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAAyB;AACvB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,kBAAiC;AAC/B,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,WAA2C;AACzC,QAAI,CAAC,KAAK,OAAO;AACf,YAAM,IAAI,MAAM,qBAAoB,qBAAqB;AAAA,IAC3D;AACA,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,yBAAyD;AACvD,WAAO,KAAK,SAAA;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,eACJ,SACA,cAAiC,IACV;AACvB,QAAI,CAAC,KAAK,OAAO;AACf,YAAM,IAAI,MAAM,iDAAiD;AAAA,IACnE;AAEA,QAAI;AACF,YAAM,kBAAkB;AAExB,YAAM,WAAW,YAAY,IAAI,CAAC,QAAQ;AACxC,cAAM,UAAU,IAAI;AACpB,YAAI,IAAI,SAAS,UAAU;AACzB,iBAAO,IAAI,cAAc,OAAO;AAAA,QAClC;AACA,eAAO,IAAI,SAAS,UAChB,IAAI,aAAa,OAAO,IACxB,IAAI,UAAU,OAAO;AAAA,MAC3B,CAAC;AAED,YAAM,UAA+B,EAAE,SAAA;AACvC,YAAM,WAAW,MAAM,KAAK,MAAM,KAAK,iBAAiB,OAAO;AAE/D,UACE,KAAK,iBACL,KAAK,QAAQ,oBAAoB,eACjC;AACA,cAAM,KAAK,wBAAwB,UAAU,OAAO;AAAA,MACtD;AAEA,WAAK,OAAO,KAAK,gCAAgC;AACjD,aAAO;AAAA,IACT,SAAS,OAAO;AACd,WAAK,OAAO,MAAM,6BAA6B,KAAK;AACpD,YAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,sBACJ,YACuB;AACvB,QAAI,CAAC,KAAK,OAAO;AACf,YAAM,IAAI,MAAM,qBAAoB,qBAAqB;AAAA,IAC3D;AAEA,QAAI;AACF,WAAK,OAAO,KAAK,+BAA+B;AAAA,QAC9C,QAAQ,WAAW;AAAA,QACnB,UAAU,WAAW;AAAA,QACrB,eAAe,OAAO,KAAK,WAAW,cAAc,CAAA,CAAE;AAAA,QACtD,YAAY,CAAC,CAAC,WAAW;AAAA,MAAA,CAC1B;AACD,YAAM,WAAW,MAAM,KAAK,MAAM,sBAAsB,UAAU;AAClE,WAAK,OAAO,KAAK,wCAAwC;AACzD,aAAO;AAAA,IACT,SAAS,OAAO;AACd,WAAK,OAAO,MAAM,qCAAqC,KAAK;AAC5D,YAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASQ,gBAAgB,WAAoB,YAA2B;AACrE,QAAI,CAAC,aAAa,CAAC,YAAY;AAC7B,YAAM,IAAI,MAAM,yCAAyC;AAAA,IAC3D;AAEA,QAAI,OAAO,cAAc,UAAU;AACjC,YAAM,IAAI;AAAA,QACR,yCAAyC,OAAO,SAAS;AAAA,MAAA;AAAA,IAE7D;AAEA,QAAI,OAAO,eAAe,UAAU;AAClC,YAAM,IAAI;AAAA,QACR,0CAA0C,OAAO,UAAU,KAAK,KAAK;AAAA,UACnE;AAAA,QAAA,CACD;AAAA,MAAA;AAAA,IAEL;AAEA,QAAI,WAAW,SAAS,IAAI;AAC1B,YAAM,IAAI,MAAM,+CAA+C;AAAA,IACjE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,iBAA+B;AACrC,UAAM,EAAE,oBAAoB,CAAA,GAAI,eAAA,IAAmB,KAAK;AAExD,UAAM,kBAAkB;AAAA,MACtB,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,IAAA;AAGP,UAAM,cAAc,wBAAA;AAEpB,QAAI,gBAAgB;AAClB,YAAM,aAAa,IAAI,IAAI,cAAc;AACzC,YAAM,kBAAkB,CAAC,GAAG,iBAAiB,GAAG,WAAW,EAAE;AAAA,QAC3D,CAAC,WAAW,WAAW,IAAI,OAAO,EAAE;AAAA,MAAA;AAEtC,aAAO,CAAC,GAAG,iBAAiB,GAAG,iBAAiB;AAAA,IAClD;AAEA,WAAO,CAAC,GAAG,iBAAiB,GAAG,aAAa,GAAG,iBAAiB;AAAA,EAClE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUQ,kBACN,cACA,KACA,YACmC;AACnC,UAAM;AAAA,MACJ,kBAAkB;AAAA,MAClB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,UAAU;AAAA,MACV;AAAA,MACA;AAAA,MACA,YAAY;AAAA,IAAA,IACV,KAAK;AAET,WAAO;AAAA,MACL,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,WAAW;AAAA,QACT,MAAM,oBAAoB,eAAe,WAAW;AAAA,QACpD;AAAA,QACA,GAAI,iBAAiB,EAAE,cAAA;AAAA,QACvB,GAAI,wCAAwC,UAAa;AAAA,UACvD;AAAA,UAEA,0BAA0B;AAAA,QAAA;AAAA,MAC5B;AAAA,MAEF,IAAI;AAAA,QACF,UAAU,IAAI,kBAAkB,GAAG;AAAA,QACnC,aAAa;AAAA,MAAA;AAAA,MAEf,WAAW;AAAA,QACT,eAAe,CAAC,SAAkC;AAChD,cAAI,KAAK,SAAS,+BAAgC,QAAO;AACzD,cAAI,KAAK,QAAQ,cAAc,CAAC,KAAK,QAAQ,WAAW,IAAI,GAAG;AAC7D,mBAAO;AAAA,UACT;AACA,iBAAO;AAAA,QACT;AAAA,MAAA;AAAA,MAEF,WAAW;AAAA,QACT,gBACE,+BAA+B,iBAAiB,SAAS;AAAA,QAC3D,GAAI,gCAAgC;AAAA,UAClC,iBAAiB;AAAA,QAAA;AAAA,QAEnB,aAAa;AAAA,MAAA;AAAA,MAEf,YAAY;AAAA,QACV,SAAS;AAAA,QACT,GAAI,oBAAoB;AAAA,UACtB,cAAc;AAAA,QAAA;AAAA,MAChB;AAAA,MAEF,GAAI,KAAK,QAAQ,cAAc;AAAA,QAC7B,KAAK;AAAA,UACH,SAAS,KAAK,QAAQ;AAAA,UACtB,aAAa;AAAA,QAAA;AAAA,MACf;AAAA,MAEF,OAAO;AAAA,QACL;AAAA,QACA,QAAQ,kBAAkB;AAAA,MAAA;AAAA,IAC5B;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,qBAAqB,YAAgC;AAC3D,UAAM,QAAQ,WAAW,KAAK,CAAC,MAAM,EAAE,OAAO,QAAQ;AACtD,QAAI,OAAO;AAEP,YACA,YAAY;AAAA,QACZ,cAAc,KAAK;AAAA,MAAA;AAAA,IAEvB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAe,YACb,SACA,SACqB;AACrB,WAAO,IAAI,qBAAoB;AAAA,MAC7B,GAAG;AAAA,MACH,gBAAgB;AAAA,IAAA,CACjB;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,QAAQ,SAA0D;AACvE,WAAO,KAAK,YAAY,SAAS,CAAC,WAAW,CAAC;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,SAAS,SAA0D;AACxE,WAAO,KAAK,YAAY,SAAS,CAAC,OAAO,CAAC;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,UAAU,SAA0D;AACzE,WAAO,KAAK,YAAY,SAAS,CAAC,QAAQ,CAAC;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,aACL,SACqB;AACrB,WAAO,KAAK,YAAY,SAAS,CAAC,UAAU,CAAC;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,YAAY,SAA0D;AAC3E,WAAO,KAAK,YAAY,SAAS,CAAC,SAAS,CAAC;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,gBACL,SACqB;AACrB,WAAO,KAAK,YAAY,SAAS,CAAC,cAAc,CAAC;AAAA,EACnD;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,qBACL,SACqB;AACrB,WAAO,KAAK,YAAY,SAAS,CAAC,mBAAmB,CAAC;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,kBACL,SACqB;AACrB,WAAO,KAAK,YAAY,SAAS,CAAC,gBAAgB,CAAC;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,iBACL,SACqB;AACrB,WAAO,KAAK,YAAY,SAAS,CAAC,UAAU,SAAS,UAAU,CAAC;AAAA,EAClE;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,QAAQ,SAA0D;AACvE,WAAO,KAAK,YAAY,SAAS,EAAE;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,QACL,SACA,YACqB;AACrB,WAAO,IAAI,qBAAoB;AAAA,MAC7B,GAAG;AAAA,MACH;AAAA,IAAA,CACD;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAc,wBACZ,UACA,iBACe;AACf,QAAI,CAAC,KAAK,iBAAiB,CAAC,KAAK,aAAa;AAC5C;AAAA,IACF;AAEA,QAAI;AACF,WAAK,OAAO,KAAK,sCAAsC;AAEvD,YAAM,eAAe,KAAK,oBAAoB,QAAQ;AAEtD,YAAM,eAAe,MAAM,KAAK,YAAY,gBAAgB,KAAK;AAAA,QAC/D,UAAU;AAAA,QACV,aAAa;AAAA,MAAA,CACd;AAED,UAAI;AACF,cAAM,WAAW,KAAK,MAAM,YAAY;AAExC,mBAAW,UAAU,UAAU;AAC7B,cACE,UACA,OAAO,WAAW,YAClB,UAAU,UACV,UAAU,UACV,QAAQ,QACR;AACA,iBAAK,OAAO;AAAA,cACV,mBAAmB,OAAO,IAAI,KAAK,OAAO,IAAI,QAAQ,OAAO,EAAE;AAAA,YAAA;AAGjE,kBAAM,gBAAgB,KAAK,qBAAqB,QAAQ;AACxD,kBAAM,QAAQ,OAAO,OAAO,EAAE;AAC9B,kBAAM,aAAa,iBAAiB,KAAK,KAAK;AAC9C,gBAAI,CAAC,YAAY;AACf,mBAAK,OAAO,KAAK,0CAA0C;AAAA,gBACzD,IAAI;AAAA,gBACJ,MAAM,OAAO,OAAO,IAAI;AAAA,gBACxB,MAAM,OAAO,OAAO,IAAI;AAAA,cAAA,CACzB;AAAA,YACH,OAAO;AACL,mBAAK,cAAc;AAAA,gBACjB;AAAA,gBACA,OAAO,OAAO,IAAI;AAAA,gBAClB,OAAO,OAAO,IAAI;AAAA,gBAClB;AAAA,cAAA;AAAA,YAEJ;AAAA,UACF;AAAA,QACF;AAEA,YAAI,SAAS,SAAS,GAAG;AACvB,eAAK,OAAO;AAAA,YACV,UAAU,SAAS,MAAM;AAAA,UAAA;AAAA,QAE7B,OAAO;AACL,eAAK,OAAO,KAAK,kDAAkD;AAAA,QACrE;AAAA,MACF,SAAS,YAAY;AACnB,aAAK,OAAO;AAAA,UACV;AAAA,UACA;AAAA,QAAA;AAEF,cAAM;AAAA,MACR;AAAA,IACF,SAAS,OAAO;AACd,WAAK,OAAO,MAAM,6BAA6B,KAAK;AACpD,YAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,qBAAqB,UAAuC;AAClE,QAAI;AACF,UACE,OAAO,aAAa,YACpB,YACA,mBAAmB,UACnB;AACA,cAAM,mBAAmB;AACzB,eAAO,OAAO,iBAAiB,kBAAkB,WAC7C,iBAAiB,gBACjB;AAAA,MACN;AACA,UAAI,OAAO,aAAa,UAAU;AAChC,cAAM,QAAQ,SAAS;AAAA,UACrB;AAAA,QAAA;AAEF,eAAO,QAAQ,MAAM,CAAC,IAAI;AAAA,MAC5B;AACA,aAAO;AAAA,IACT,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,aAAmB;AACzB,QAAI,CAAC,KAAK,SAAS,CAAC,KAAK,QAAQ,YAAY;AAC3C;AAAA,IACF;AAEA,SAAK,MACF,kBAAA,EACA,MAAM,CAAC,MAAM;AACZ,WAAK,OAAO,MAAM,kCAAkC,CAAC;AAAA,IACvD,CAAC,EACA,KAAK,MAAM;AACV,WAAK,OAAO,KAAK,oCAAoC;AAAA,IACvD,CAAC;AAAA,EACL;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,yBAA2D;AACzD,QAAI,KAAK,OAAO;AACd,aAAO,KAAK,MAAM,uBAAA;AAAA,IACpB;AACA,+BAAW,IAAA;AAAA,EACb;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,qBAAqB,YAA6B;AAChD,QAAI,KAAK,OAAO;AACd,YAAM,YAAY,KAAK,MAAM,uBAAA;AAC7B,YAAM,SAAS,UAAU,IAAI,UAAU;AACvC,aAAO,QAAQ,aAAa;AAAA,IAC9B;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,UAAyB;AAC7B,QAAI;AACF,WAAK,OAAO,KAAK,oCAAoC;AAErD,UAAI,KAAK,eAAe;AACtB,YAAI;AACF,eAAK,cAAc,QAAA;AACnB,eAAK,OAAO,KAAK,wCAAwC;AAAA,QAC3D,SAAS,OAAO;AACd,eAAK,OAAO,KAAK,qCAAqC,KAAK;AAAA,QAC7D;AACA,aAAK,gBAAgB;AAAA,MACvB;AAEA,UAAI,KAAK,qBAAqB;AAC5B,cAAM,KAAK,oBAAoB,QAAA;AAC/B,aAAK,OAAO,KAAK,gCAAgC;AAAA,MACnD;AAEA,WAAK,OAAO,KAAK,uCAAuC;AAAA,IAC1D,SAAS,OAAO;AACd,WAAK,OAAO,MAAM,yBAAyB,KAAK;AAAA,IAClD;AAAA,EACF;AAAA,EAEQ,oBAAoB,UAA2B;AACrD,QAAI,OAAO,aAAa,UAAU;AAChC,aAAO;AAAA,IACT;AAEA,QAAI,YAAY,OAAO,aAAa,YAAY,YAAY,UAAU;AACpE,YAAM,qBAAqB;AAC3B,aAAO,OAAO,mBAAmB,MAAM;AAAA,IACzC;AAEA,WAAO,KAAK,UAAU,QAAQ;AAAA,EAChC;AACF;AArxBE,qBAAwB,wBACtB;AAFG,IAAM,sBAAN;"}
@@ -1,4 +1,4 @@
1
- import { LangChainAgent } from "./index31.js";
1
+ import { LangChainAgent } from "./index33.js";
2
2
  function createAgent(config) {
3
3
  const framework = config.framework || "langchain";
4
4
  switch (framework) {
@@ -28,7 +28,7 @@ export interface ConversationalAgentOptions {
28
28
  network?: NetworkType;
29
29
  openAIApiKey: string;
30
30
  openAIModelName?: string;
31
- llmProvider?: 'openai' | 'anthropic';
31
+ llmProvider?: 'openai' | 'anthropic' | 'openrouter';
32
32
  verbose?: boolean;
33
33
  operationalMode?: AgentOperationalMode;
34
34
  userAccountId?: string;
@@ -49,6 +49,16 @@ export interface ConversationalAgentOptions {
49
49
  entityMemoryEnabled?: boolean;
50
50
  /** Configuration for entity memory system */
51
51
  entityMemoryConfig?: SmartMemoryConfig;
52
+ /**
53
+ * Provider used for entity extraction/resolution tools (defaults to llmProvider or 'openai')
54
+ */
55
+ entityMemoryProvider?: 'openai' | 'anthropic' | 'openrouter';
56
+ /**
57
+ * Model name for entity extraction/resolution tools (defaults per provider)
58
+ */
59
+ entityMemoryModelName?: string;
60
+ openRouterApiKey?: string;
61
+ openRouterBaseURL?: string;
52
62
  }
53
63
  /**
54
64
  * The ConversationalAgent class is an optional wrapper around the HederaConversationalAgent class,
@@ -15,6 +15,8 @@ export interface EntityAssociation {
15
15
  createdAt: Date;
16
16
  /** Transaction ID that created this entity */
17
17
  transactionId?: string;
18
+ /** Optional session identifier to scope associations */
19
+ sessionId?: string;
18
20
  }
19
21
  /**
20
22
  * Options for resolving entity references
@@ -224,7 +226,11 @@ export declare class SmartMemoryManager {
224
226
  * @param entityType - Type of entity (token, account, topic, etc.)
225
227
  * @param transactionId - Optional transaction ID that created this entity
226
228
  */
227
- storeEntityAssociation(entityId: string, entityName: string, entityType: string, transactionId?: string): void;
229
+ storeEntityAssociation(entityId: string, entityName: string, entityType: string, transactionId?: string, sessionId?: string): void;
230
+ /**
231
+ * Normalize various type aliases to canonical EntityFormat strings using a registry.
232
+ */
233
+ private normalizeEntityType;
228
234
  /**
229
235
  * Resolve entity references from natural language queries
230
236
  * @param query - Search query (entity name or natural language reference)
@@ -0,0 +1,41 @@
1
+ import { ContentStoreManager as PackageContentStoreManager } from './content-store-manager';
2
+
3
+ export interface AttachmentData {
4
+ name: string;
5
+ data: string;
6
+ type: string;
7
+ size: number;
8
+ }
9
+ type ContentStoreManager = PackageContentStoreManager;
10
+ /**
11
+ * Utility for processing file attachments and content references
12
+ */
13
+ export declare class AttachmentProcessor {
14
+ private logger;
15
+ constructor();
16
+ /**
17
+ * Process attachments and create content references
18
+ */
19
+ processAttachments(content: string, attachments: AttachmentData[], contentStoreManager?: ContentStoreManager): Promise<string>;
20
+ /**
21
+ * Process attachments using content store manager
22
+ */
23
+ private processWithContentStore;
24
+ /**
25
+ * Process attachments with simple file references
26
+ */
27
+ private processWithSimpleReferences;
28
+ /**
29
+ * Create inline reference for small files
30
+ */
31
+ private createInlineReference;
32
+ /**
33
+ * Create formatted file list
34
+ */
35
+ private createFileList;
36
+ /**
37
+ * Format file size for display
38
+ */
39
+ private formatFileSize;
40
+ }
41
+ export {};
@@ -1,3 +1,5 @@
1
1
  export * from './entity-resolver';
2
2
  export * from './content-store-manager';
3
3
  export * from './formatters';
4
+ export * from './parameter-service';
5
+ export * from './attachment-processor';
@@ -0,0 +1,43 @@
1
+ import { NetworkType } from '@hashgraphonline/standards-sdk';
2
+ import { FormatConverterRegistry } from './formatters';
3
+ import { EntityAssociation } from '../memory/smart-memory-manager';
4
+
5
+ /**
6
+ * Service for processing tool parameters and applying entity format conversions
7
+ */
8
+ export declare class ParameterService {
9
+ private logger;
10
+ private formatConverterRegistry;
11
+ private networkType;
12
+ constructor(formatConverterRegistry: FormatConverterRegistry, networkType: NetworkType);
13
+ /**
14
+ * Unified preprocessing entrypoint (DRY):
15
+ * - Optional AI-driven resolution via provided entityResolver
16
+ * - Deterministic post-pass for safe format enforcement
17
+ */
18
+ preprocessParameters(toolName: string, parameters: Record<string, unknown>, entities?: EntityAssociation[], options?: {
19
+ entityResolver?: {
20
+ resolveReferences: (message: string, entities: EntityAssociation[]) => Promise<string>;
21
+ };
22
+ sessionId?: string;
23
+ preferences?: Record<string, string>;
24
+ }): Promise<Record<string, unknown>>;
25
+ /**
26
+ * Attach unified preprocessing callback directly to the agent.
27
+ */
28
+ attachToAgent(agent: unknown, deps?: {
29
+ getSessionId?: () => string | null;
30
+ getEntities?: (sessionId: string | null) => Promise<EntityAssociation[]>;
31
+ entityResolver?: {
32
+ resolveReferences: (message: string, entities: EntityAssociation[]) => Promise<string>;
33
+ };
34
+ }): void;
35
+ /**
36
+ * Preprocess tool parameters by applying format conversions based on tool's entity resolution preferences
37
+ */
38
+ preprocessToolParameters(toolName: string, parameters: Record<string, unknown>, entities?: EntityAssociation[], sessionId?: string): Promise<Record<string, unknown>>;
39
+ /**
40
+ * Convert entity references in a parameter value based on tool preferences
41
+ */
42
+ convertParameterEntities(parameterValue: string, entities: EntityAssociation[], preferences?: Record<string, string>): Promise<string>;
43
+ }
@@ -1,5 +1,7 @@
1
1
  import { StructuredTool } from '@langchain/core/tools';
2
2
  import { z } from 'zod';
3
+ import { ChatOpenAI } from '@langchain/openai';
4
+ import { ChatAnthropic } from '@langchain/anthropic';
3
5
 
4
6
  declare const ResolveEntitiesSchema: z.ZodObject<{
5
7
  message: z.ZodString;
@@ -75,7 +77,7 @@ export declare class ResolveEntitiesTool extends StructuredTool {
75
77
  }[];
76
78
  }>;
77
79
  private llm;
78
- constructor(apiKey: string, modelName?: string);
80
+ constructor(llm: ChatOpenAI | ChatAnthropic);
79
81
  _call(input: z.infer<typeof ResolveEntitiesSchema>): Promise<string>;
80
82
  private groupEntitiesByType;
81
83
  private buildEntityContext;
@@ -94,10 +96,10 @@ export declare class ExtractEntitiesTool extends StructuredTool {
94
96
  userMessage: string;
95
97
  }>;
96
98
  private llm;
97
- constructor(apiKey: string, modelName?: string);
99
+ constructor(llm: ChatOpenAI | ChatAnthropic);
98
100
  _call(input: z.infer<typeof ExtractEntitiesSchema>): Promise<string>;
99
101
  }
100
- export declare function createEntityTools(apiKey: string, modelName?: string): {
102
+ export declare function createEntityTools(llm: ChatOpenAI | ChatAnthropic): {
101
103
  resolveEntities: ResolveEntitiesTool;
102
104
  extractEntities: ExtractEntitiesTool;
103
105
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hashgraphonline/conversational-agent",
3
- "version": "0.2.1",
3
+ "version": "0.2.103",
4
4
  "type": "module",
5
5
  "main": "./dist/cjs/index.cjs",
6
6
  "module": "./dist/esm/index.js",
@@ -100,6 +100,7 @@
100
100
  "@langchain/anthropic": "^0.3.26",
101
101
  "@langchain/core": "^0.3.72",
102
102
  "@langchain/openai": "^0.6.9",
103
+ "openai": "^5.12.2",
103
104
  "@modelcontextprotocol/sdk": "^1.17.4",
104
105
  "axios": "^1.11.0",
105
106
  "bignumber.js": "^9.3.1",
@@ -8,6 +8,7 @@ import { createAgent } from './agent-factory';
8
8
  import { LangChainProvider } from './providers';
9
9
  import type { ChatResponse, ConversationContext } from './base-agent';
10
10
  import { ChatOpenAI } from '@langchain/openai';
11
+ import OpenAI from 'openai';
11
12
  import { ChatAnthropic } from '@langchain/anthropic';
12
13
  import {
13
14
  HumanMessage,
@@ -57,7 +58,7 @@ export interface ConversationalAgentOptions {
57
58
  network?: NetworkType;
58
59
  openAIApiKey: string;
59
60
  openAIModelName?: string;
60
- llmProvider?: 'openai' | 'anthropic';
61
+ llmProvider?: 'openai' | 'anthropic' | 'openrouter';
61
62
  verbose?: boolean;
62
63
  operationalMode?: AgentOperationalMode;
63
64
  userAccountId?: string;
@@ -77,6 +78,19 @@ export interface ConversationalAgentOptions {
77
78
 
78
79
  /** Configuration for entity memory system */
79
80
  entityMemoryConfig?: SmartMemoryConfig;
81
+
82
+ /**
83
+ * Provider used for entity extraction/resolution tools (defaults to llmProvider or 'openai')
84
+ */
85
+ entityMemoryProvider?: 'openai' | 'anthropic' | 'openrouter';
86
+
87
+ /**
88
+ * Model name for entity extraction/resolution tools (defaults per provider)
89
+ */
90
+ entityMemoryModelName?: string;
91
+
92
+ openRouterApiKey?: string;
93
+ openRouterBaseURL?: string;
80
94
  }
81
95
 
82
96
  /**
@@ -121,7 +135,7 @@ export class ConversationalAgent {
121
135
  if (this.options.entityMemoryEnabled !== false) {
122
136
  if (!options.openAIApiKey) {
123
137
  throw new Error(
124
- 'OpenAI API key is required when entity memory is enabled'
138
+ 'OpenAI/Anthropic API key is required when entity memory is enabled'
125
139
  );
126
140
  }
127
141
 
@@ -130,7 +144,48 @@ export class ConversationalAgent {
130
144
  );
131
145
  this.logger.info('Entity memory initialized');
132
146
 
133
- this.entityTools = createEntityTools(options.openAIApiKey, 'gpt-4o-mini');
147
+ const provider = options.entityMemoryProvider || options.llmProvider || 'openai';
148
+ const modelName =
149
+ options.entityMemoryModelName ||
150
+ (provider === 'anthropic'
151
+ ? 'claude-3-7-sonnet-latest'
152
+ : provider === 'openrouter'
153
+ ? 'openai/gpt-4o-mini'
154
+ : 'gpt-4o-mini');
155
+
156
+ let resolverLLM: ChatOpenAI | ChatAnthropic;
157
+ if (provider === 'anthropic') {
158
+ resolverLLM = new ChatAnthropic({
159
+ apiKey: options.openAIApiKey,
160
+ model: modelName,
161
+ temperature: 0,
162
+ });
163
+ } else if (provider === 'openrouter') {
164
+ const baseURL = options.openRouterBaseURL || 'https://openrouter.ai/api/v1';
165
+ const apiKey = options.openRouterApiKey || options.openAIApiKey;
166
+ const client = new OpenAI({
167
+ apiKey,
168
+ baseURL,
169
+ defaultHeaders: {
170
+ Referer: process.env.OPENROUTER_REFERRER || 'https://hashgraphonline.com',
171
+ 'HTTP-Referer': process.env.OPENROUTER_REFERRER || 'https://hashgraphonline.com',
172
+ 'X-Title': process.env.OPENROUTER_TITLE || 'Hashgraph Online Conversational Agent',
173
+ },
174
+ });
175
+ resolverLLM = new ChatOpenAI({
176
+ client,
177
+ model: modelName,
178
+ temperature: 0,
179
+ });
180
+ } else {
181
+ resolverLLM = new ChatOpenAI({
182
+ apiKey: options.openAIApiKey,
183
+ model: modelName,
184
+ temperature: 0,
185
+ });
186
+ }
187
+
188
+ this.entityTools = createEntityTools(resolverLLM);
134
189
  this.logger.info('LLM-based entity resolver tools initialized');
135
190
  }
136
191
  }
@@ -160,12 +215,42 @@ export class ConversationalAgent {
160
215
  );
161
216
 
162
217
  let llm: ChatOpenAI | ChatAnthropic;
218
+ let providerInfo: Record<string, unknown> = { provider: llmProvider };
163
219
  if (llmProvider === 'anthropic') {
164
220
  llm = new ChatAnthropic({
165
221
  apiKey: openAIApiKey,
166
- modelName: openAIModelName || 'claude-3-5-sonnet-20241022',
222
+ model: openAIModelName || 'claude-3-7-sonnet-latest',
167
223
  temperature: DEFAULT_TEMPERATURE,
168
224
  });
225
+ providerInfo = {
226
+ ...providerInfo,
227
+ model: openAIModelName || 'claude-3-7-sonnet-latest',
228
+ keyPresent: !!openAIApiKey,
229
+ };
230
+ } else if (llmProvider === 'openrouter') {
231
+ const baseURL = this.options.openRouterBaseURL || 'https://openrouter.ai/api/v1';
232
+ const apiKey = this.options.openRouterApiKey || openAIApiKey;
233
+ const modelName = openAIModelName || 'anthropic/claude-3-haiku-20240307';
234
+ const client = new OpenAI({
235
+ apiKey,
236
+ baseURL,
237
+ defaultHeaders: {
238
+ Referer: process.env.OPENROUTER_REFERRER || 'https://hashgraphonline.com',
239
+ 'HTTP-Referer': process.env.OPENROUTER_REFERRER || 'https://hashgraphonline.com',
240
+ 'X-Title': process.env.OPENROUTER_TITLE || 'Hashgraph Online Conversational Agent',
241
+ },
242
+ });
243
+ llm = new ChatOpenAI({
244
+ client,
245
+ model: modelName,
246
+ temperature: DEFAULT_TEMPERATURE,
247
+ });
248
+ providerInfo = {
249
+ ...providerInfo,
250
+ model: modelName,
251
+ baseURL,
252
+ keyPresent: !!apiKey,
253
+ };
169
254
  } else {
170
255
  const modelName = openAIModelName || 'gpt-4o-mini';
171
256
  const isGPT5Model =
@@ -173,13 +258,20 @@ export class ConversationalAgent {
173
258
  modelName.toLowerCase().includes('gpt5');
174
259
  llm = new ChatOpenAI({
175
260
  apiKey: openAIApiKey,
176
- modelName: openAIModelName,
261
+ model: modelName,
177
262
  ...(isGPT5Model
178
263
  ? { temperature: 1 }
179
264
  : { temperature: DEFAULT_TEMPERATURE }),
180
265
  });
266
+ providerInfo = {
267
+ ...providerInfo,
268
+ model: modelName,
269
+ keyPresent: !!openAIApiKey,
270
+ };
181
271
  }
182
272
 
273
+ this.logger.info('AI provider configured', providerInfo);
274
+
183
275
  this.logger.info('Preparing plugins...');
184
276
  const allPlugins = this.preparePlugins();
185
277
  this.logger.info('Creating agent config...');
@@ -378,7 +378,7 @@ export class FormAwareAgentExecutor extends AgentExecutor {
378
378
  toolName: toolName,
379
379
  toolDescription: tool.description,
380
380
  },
381
- missingFields // Pass undefined for focused schemas, Set<string> for others
381
+ missingFields
382
382
  );
383
383
 
384
384
  if (this.isZodObject(schemaToUse)) {
@@ -621,46 +621,56 @@ export class LangChainAgent extends BaseAgent {
621
621
  );
622
622
  }
623
623
 
624
- const parsedSteps = result?.intermediateSteps?.[0]?.observation;
625
- if (
626
- parsedSteps &&
627
- typeof parsedSteps === 'string' &&
628
- this.isJSON(parsedSteps)
629
- ) {
624
+ const steps = (result?.intermediateSteps as IntermediateStep[]) || [];
625
+ const lastJsonObservation = [...steps]
626
+ .reverse()
627
+ .find(
628
+ (s) => typeof s?.observation === 'string' && this.isJSON(s.observation as string)
629
+ )?.observation as string | undefined;
630
+
631
+ if (lastJsonObservation) {
630
632
  try {
631
- const parsed = JSON.parse(parsedSteps);
633
+ const parsed = JSON.parse(lastJsonObservation);
632
634
 
633
635
  if (ResponseFormatter.isInscriptionResponse(parsed)) {
634
- const formattedMessage =
635
- ResponseFormatter.formatInscriptionResponse(parsed);
636
+ const formattedMessage = ResponseFormatter.formatInscriptionResponse(parsed);
636
637
  response.output = formattedMessage;
637
638
  response.message = formattedMessage;
638
-
639
639
  if (parsed.inscription) {
640
640
  response.inscription = parsed.inscription;
641
641
  }
642
642
  if (parsed.metadata) {
643
+ response.metadata = { ...response.metadata, ...parsed.metadata };
644
+ }
645
+ } else {
646
+ if (typeof parsed.message === 'string' && parsed.message.trim().length > 0) {
647
+ response.message = parsed.message;
648
+ response.output = parsed.message;
649
+ }
650
+ if (parsed.success === true) {
651
+ delete (response as { error?: string }).error;
652
+ }
653
+ if (typeof parsed.transactionBytes === 'string') {
643
654
  response.metadata = {
644
655
  ...response.metadata,
645
- ...parsed.metadata,
656
+ transactionBytes: parsed.transactionBytes as string,
646
657
  };
647
658
  }
648
- } else {
649
- response = { ...response, ...parsed };
659
+ if (typeof parsed.scheduleId === 'string') {
660
+ (response as { scheduleId?: string }).scheduleId = parsed.scheduleId as string;
661
+ }
650
662
  }
651
663
 
652
664
  const blockMetadata = this.processHashLinkBlocks(parsed);
653
665
  if (blockMetadata.hashLinkBlock) {
654
- response.metadata = {
655
- ...response.metadata,
656
- ...blockMetadata,
657
- };
666
+ response.metadata = { ...response.metadata, ...blockMetadata };
658
667
  }
659
668
  } catch (error) {
660
669
  this.logger.error('Error parsing intermediate steps:', error);
661
670
  }
662
671
  }
663
672
 
673
+
664
674
  if (!response.output || response.output.trim() === '') {
665
675
  response.output = 'Agent action complete.';
666
676
  }
@@ -770,7 +780,15 @@ export class LangChainAgent extends BaseAgent {
770
780
  this.config.ai?.modelName ||
771
781
  process.env.OPENAI_MODEL_NAME ||
772
782
  'gpt-4o-mini';
773
- this.tokenTracker = new TokenUsageCallbackHandler(modelName);
783
+ try {
784
+ if (typeof (TokenUsageCallbackHandler as unknown as { new (m: string): unknown }) === 'function') {
785
+ this.tokenTracker = new TokenUsageCallbackHandler(modelName);
786
+ } else {
787
+ this.logger.warn('TokenUsageCallbackHandler unavailable or not a constructor; skipping token tracking');
788
+ }
789
+ } catch {
790
+ this.logger.warn('TokenUsageCallbackHandler threw; skipping token tracking');
791
+ }
774
792
 
775
793
  this.toolRegistry = new ToolRegistry(this.logger);
776
794