@hashgraphonline/conversational-agent 0.1.211 → 0.1.214

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../../src/plugins/hcs-10/HCS10Plugin.ts","../../src/plugins/hcs-2/HCS2Plugin.ts","../../src/plugins/inscribe/InscribePlugin.ts","../../src/plugins/hbar/AccountBuilder.ts","../../src/plugins/hbar/TransferHbarTool.ts","../../src/plugins/hbar/AirdropToolWrapper.ts","../../src/plugins/hbar/HbarPlugin.ts","../../src/langchain/ContentAwareAgentExecutor.ts","../../src/base-agent.ts","../../src/mcp/ContentProcessor.ts","../../src/mcp/MCPClientManager.ts","../../src/mcp/adapters/langchain.ts","../../src/memory/TokenCounter.ts","../../src/memory/MemoryWindow.ts","../../src/memory/ReferenceIdGenerator.ts","../../src/types/content-reference.ts","../../src/memory/ContentStorage.ts","../../src/memory/SmartMemoryManager.ts","../../src/langchain-agent.ts","../../src/agent-factory.ts","../../src/providers.ts","../../src/config/system-message.ts","../../src/services/ContentStoreManager.ts","../../src/tools/EntityResolverTool.ts","../../src/conversational-agent.ts","../../src/mcp/helpers.ts"],"sourcesContent":["import {\n GenericPluginContext,\n HederaTool,\n BasePlugin,\n HederaAgentKit,\n} from 'hedera-agent-kit';\nimport {\n IStateManager,\n OpenConvaiState,\n HCS10Builder,\n RegisterAgentTool,\n FindRegistrationsTool,\n InitiateConnectionTool,\n ListConnectionsTool,\n SendMessageToConnectionTool,\n CheckMessagesTool,\n ConnectionMonitorTool,\n ManageConnectionRequestsTool,\n AcceptConnectionRequestTool,\n RetrieveProfileTool,\n ListUnapprovedConnectionRequestsTool,\n} from '@hashgraphonline/standards-agent-kit';\nimport { HCS10Client } from '@hashgraphonline/standards-sdk';\n\nexport class HCS10Plugin extends BasePlugin {\n id = 'hcs-10';\n name = 'HCS-10 Plugin';\n description =\n 'HCS-10 agent tools for decentralized agent registration, connections, and messaging on Hedera';\n version = '1.0.0';\n author = 'Hashgraph Online';\n namespace = 'hcs10';\n\n private stateManager?: IStateManager;\n private tools: HederaTool[] = [];\n appConfig?: Record<string, unknown>;\n\n override async initialize(context: GenericPluginContext): Promise<void> {\n await super.initialize(context);\n\n const hederaKit = context.config.hederaKit as HederaAgentKit;\n if (!hederaKit) {\n this.context.logger.warn(\n 'HederaKit not found in context. HCS-10 tools will not be available.'\n );\n return;\n }\n\n try {\n this.stateManager =\n (context.stateManager as IStateManager) ||\n (context.config.stateManager as IStateManager) ||\n (this.appConfig?.stateManager as IStateManager) ||\n new OpenConvaiState();\n\n const accountId = hederaKit.signer.getAccountId().toString();\n let inboundTopicId = '';\n let outboundTopicId = '';\n\n try {\n const opKey = hederaKit.signer.getOperatorPrivateKey() as {\n toString?: () => string;\n toStringRaw?: () => string;\n };\n const privateKey = typeof opKey?.toStringRaw === 'function'\n ? opKey.toStringRaw()\n : typeof opKey?.toString === 'function'\n ? opKey.toString()\n : String(opKey);\n\n const hcs10Client = new HCS10Client({\n network: hederaKit.network as 'mainnet' | 'testnet',\n operatorId: accountId,\n operatorPrivateKey: privateKey,\n logLevel: 'error',\n });\n\n const profileResponse = await hcs10Client.retrieveProfile(accountId);\n if (profileResponse.success && profileResponse.topicInfo) {\n inboundTopicId = profileResponse.topicInfo.inboundTopic;\n outboundTopicId = profileResponse.topicInfo.outboundTopic;\n }\n } catch (profileError) {\n this.context.logger.warn(\n 'Could not retrieve profile topics:',\n profileError\n );\n }\n\n this.stateManager.setCurrentAgent({\n name: `Agent ${accountId}`,\n accountId: accountId,\n inboundTopicId,\n outboundTopicId,\n privateKey: ((): string => {\n const opKey = hederaKit.signer.getOperatorPrivateKey() as {\n toString?: () => string;\n toStringRaw?: () => string;\n };\n return typeof opKey?.toStringRaw === 'function'\n ? opKey.toStringRaw()\n : typeof opKey?.toString === 'function'\n ? opKey.toString()\n : String(opKey);\n })(),\n });\n\n this.context.logger.info(\n `Set current agent: ${accountId} with topics ${inboundTopicId}/${outboundTopicId}`\n );\n\n if (this.stateManager && !this.stateManager.getConnectionsManager()) {\n try {\n const opKey = hederaKit.signer.getOperatorPrivateKey() as {\n toString?: () => string;\n toStringRaw?: () => string;\n };\n const privateKey = typeof opKey?.toStringRaw === 'function'\n ? opKey.toStringRaw()\n : typeof opKey?.toString === 'function'\n ? opKey.toString()\n : String(opKey);\n const hcs10Client = new HCS10Client({\n network: hederaKit.network as 'mainnet' | 'testnet',\n operatorId: accountId,\n operatorPrivateKey: privateKey,\n logLevel: 'error',\n });\n\n this.stateManager.initializeConnectionsManager(hcs10Client as any);\n this.context.logger.info(\n 'ConnectionsManager initialized in HCS10Plugin'\n );\n } catch (cmError) {\n this.context.logger.warn('Could not initialize ConnectionsManager:', cmError);\n }\n }\n\n this.initializeTools();\n\n this.context.logger.info('HCS-10 Plugin initialized successfully');\n } catch (error) {\n this.context.logger.error('Failed to initialize HCS-10 plugin:', error);\n }\n }\n\n private initializeTools(): void {\n if (!this.stateManager) {\n throw new Error('StateManager must be initialized before creating tools');\n }\n\n const hederaKit = this.context.config.hederaKit as HederaAgentKit;\n if (!hederaKit) {\n throw new Error('HederaKit not found in context config');\n }\n\n const hcs10Builder = new HCS10Builder(hederaKit, this.stateManager);\n\n this.tools = [\n new RegisterAgentTool({\n hederaKit: hederaKit,\n hcs10Builder: hcs10Builder,\n logger: this.context.logger,\n }),\n new FindRegistrationsTool({\n hederaKit: hederaKit,\n hcs10Builder: hcs10Builder,\n logger: this.context.logger,\n }),\n new RetrieveProfileTool({\n hederaKit: hederaKit,\n hcs10Builder: hcs10Builder,\n logger: this.context.logger,\n }),\n new InitiateConnectionTool({\n hederaKit: hederaKit,\n hcs10Builder: hcs10Builder,\n logger: this.context.logger,\n }),\n new ListConnectionsTool({\n hederaKit: hederaKit,\n hcs10Builder: hcs10Builder,\n logger: this.context.logger,\n }),\n new SendMessageToConnectionTool({\n hederaKit: hederaKit,\n hcs10Builder: hcs10Builder,\n logger: this.context.logger,\n }),\n new CheckMessagesTool({\n hederaKit: hederaKit,\n hcs10Builder: hcs10Builder,\n logger: this.context.logger,\n }),\n new ConnectionMonitorTool({\n hederaKit: hederaKit,\n hcs10Builder: hcs10Builder,\n logger: this.context.logger,\n }),\n new ManageConnectionRequestsTool({\n hederaKit: hederaKit,\n hcs10Builder: hcs10Builder,\n logger: this.context.logger,\n }),\n new AcceptConnectionRequestTool({\n hederaKit: hederaKit,\n hcs10Builder: hcs10Builder,\n logger: this.context.logger,\n }),\n new ListUnapprovedConnectionRequestsTool({\n hederaKit: hederaKit,\n hcs10Builder: hcs10Builder,\n logger: this.context.logger,\n }),\n ];\n }\n\n getTools(): HederaTool[] {\n return this.tools;\n }\n\n getStateManager(): IStateManager | undefined {\n return this.stateManager;\n }\n\n override async cleanup(): Promise<void> {\n this.tools = [];\n delete this.stateManager;\n if (this.context?.logger) {\n this.context.logger.info('HCS-10 Plugin cleaned up');\n }\n }\n}\n","import {\n GenericPluginContext,\n HederaTool,\n BasePlugin,\n HederaAgentKit,\n} from 'hedera-agent-kit';\nimport {\n HCS2Builder,\n CreateRegistryTool,\n RegisterEntryTool,\n UpdateEntryTool,\n DeleteEntryTool,\n MigrateRegistryTool,\n QueryRegistryTool,\n} from '@hashgraphonline/standards-agent-kit';\n\n/**\n * Plugin providing HCS-2 registry management tools\n */\nexport class HCS2Plugin extends BasePlugin {\n id = 'hcs-2';\n name = 'HCS-2 Plugin';\n description =\n 'HCS-2 registry management tools for decentralized registries on Hedera';\n version = '1.0.0';\n author = 'Hashgraph Online';\n namespace = 'hcs2';\n\n private tools: HederaTool[] = [];\n\n override async initialize(context: GenericPluginContext): Promise<void> {\n await super.initialize(context);\n\n const hederaKit = context.config.hederaKit as HederaAgentKit;\n if (!hederaKit) {\n this.context.logger.warn(\n 'HederaKit not found in context. HCS-2 tools will not be available.'\n );\n return;\n }\n\n try {\n this.initializeTools();\n\n this.context.logger.info(\n 'HCS-2 Plugin initialized successfully'\n );\n } catch (error) {\n this.context.logger.error(\n 'Failed to initialize HCS-2 plugin:',\n error\n );\n }\n }\n\n private initializeTools(): void {\n const hederaKit = this.context.config.hederaKit as HederaAgentKit;\n if (!hederaKit) {\n throw new Error('HederaKit not found in context config');\n }\n\n const hcs2Builder = new HCS2Builder(hederaKit);\n\n this.tools = [\n new CreateRegistryTool({\n hederaKit: hederaKit,\n hcs2Builder: hcs2Builder,\n logger: this.context.logger,\n }),\n new RegisterEntryTool({\n hederaKit: hederaKit,\n hcs2Builder: hcs2Builder,\n logger: this.context.logger,\n }),\n new UpdateEntryTool({\n hederaKit: hederaKit,\n hcs2Builder: hcs2Builder,\n logger: this.context.logger,\n }),\n new DeleteEntryTool({\n hederaKit: hederaKit,\n hcs2Builder: hcs2Builder,\n logger: this.context.logger,\n }),\n new MigrateRegistryTool({\n hederaKit: hederaKit,\n hcs2Builder: hcs2Builder,\n logger: this.context.logger,\n }),\n new QueryRegistryTool({\n hederaKit: hederaKit,\n hcs2Builder: hcs2Builder,\n logger: this.context.logger,\n }),\n ];\n }\n\n getTools(): HederaTool[] {\n return this.tools;\n }\n\n override async cleanup(): Promise<void> {\n this.tools = [];\n if (this.context?.logger) {\n this.context.logger.info('HCS-2 Plugin cleaned up');\n }\n }\n}","import {\n GenericPluginContext,\n HederaTool,\n BasePlugin,\n HederaAgentKit,\n} from 'hedera-agent-kit';\nimport {\n InscriberBuilder,\n InscribeFromUrlTool,\n InscribeFromFileTool,\n InscribeFromBufferTool,\n InscribeHashinalTool,\n RetrieveInscriptionTool,\n} from '@hashgraphonline/standards-agent-kit';\n\n/**\n * Plugin providing content inscription tools for Hedera\n */\nexport class InscribePlugin extends BasePlugin {\n id = 'inscribe';\n name = 'Inscribe Plugin';\n description =\n 'Content inscription tools for storing data on Hedera Consensus Service';\n version = '1.0.0';\n author = 'Hashgraph Online';\n namespace = 'inscribe';\n\n private tools: HederaTool[] = [];\n\n override async initialize(context: GenericPluginContext): Promise<void> {\n await super.initialize(context);\n\n const hederaKit = context.config.hederaKit as HederaAgentKit;\n if (!hederaKit) {\n this.context.logger.warn(\n 'HederaKit not found in context. Inscription tools will not be available.'\n );\n return;\n }\n\n try {\n this.initializeTools();\n\n this.context.logger.info(\n 'Inscribe Plugin initialized successfully'\n );\n } catch (error) {\n this.context.logger.error(\n 'Failed to initialize Inscribe plugin:',\n error\n );\n }\n }\n\n private initializeTools(): void {\n const hederaKit = this.context.config.hederaKit as HederaAgentKit;\n if (!hederaKit) {\n throw new Error('HederaKit not found in context config');\n }\n\n const inscriberBuilder = new InscriberBuilder(hederaKit);\n\n this.tools = [\n new InscribeFromUrlTool({\n hederaKit: hederaKit,\n inscriberBuilder: inscriberBuilder,\n logger: this.context.logger,\n }),\n new InscribeFromFileTool({\n hederaKit: hederaKit,\n inscriberBuilder: inscriberBuilder,\n logger: this.context.logger,\n }),\n new InscribeFromBufferTool({\n hederaKit: hederaKit,\n inscriberBuilder: inscriberBuilder,\n logger: this.context.logger,\n }),\n new InscribeHashinalTool({\n hederaKit: hederaKit,\n inscriberBuilder: inscriberBuilder,\n logger: this.context.logger,\n }),\n new RetrieveInscriptionTool({\n hederaKit: hederaKit,\n inscriberBuilder: inscriberBuilder,\n logger: this.context.logger,\n }),\n ];\n }\n\n getTools(): HederaTool[] {\n return this.tools;\n }\n\n override async cleanup(): Promise<void> {\n this.tools = [];\n if (this.context?.logger) {\n this.context.logger.info('Inscribe Plugin cleaned up');\n }\n }\n}","import {\n AccountId,\n Hbar,\n TransferTransaction,\n} from '@hashgraph/sdk';\nimport BigNumber from 'bignumber.js';\nimport { HederaAgentKit, BaseServiceBuilder } from 'hedera-agent-kit';\nimport { HbarTransferParams } from './types';\n\n/**\n * Custom AccountBuilder that properly handles HBAR decimal conversion\n */\nexport class AccountBuilder extends BaseServiceBuilder {\n constructor(hederaKit: HederaAgentKit) {\n super(hederaKit);\n }\n\n /**\n * Transfers HBAR between accounts with proper decimal handling\n */\n public transferHbar(\n params: HbarTransferParams,\n isUserInitiated: boolean = true\n ): this {\n this.clearNotes();\n const transaction = new TransferTransaction();\n \n if (!params.transfers || params.transfers.length === 0) {\n throw new Error('HbarTransferParams must include at least one transfer.');\n }\n\n let netZeroInTinybars = new BigNumber(0);\n let userTransferProcessedForScheduling = false;\n\n if (\n isUserInitiated &&\n this.kit.userAccountId &&\n (this.kit.operationalMode as string) === 'provideBytes' &&\n params.transfers.length === 1\n ) {\n const receiverTransfer = params.transfers[0];\n const amountValue =\n typeof receiverTransfer.amount === 'string' ||\n typeof receiverTransfer.amount === 'number'\n ? receiverTransfer.amount\n : receiverTransfer.amount.toString();\n\n const amountBigNum = new BigNumber(amountValue);\n\n if (amountBigNum.isPositive()) {\n const recipientAccountId =\n typeof receiverTransfer.accountId === 'string'\n ? AccountId.fromString(receiverTransfer.accountId)\n : receiverTransfer.accountId;\n\n const roundedAmount = amountBigNum.toFixed(8, BigNumber.ROUND_DOWN);\n const sdkHbarAmount = Hbar.fromString(roundedAmount);\n\n this.logger.info(\n `[AccountBuilder.transferHbar] Configuring user-initiated scheduled transfer: ${sdkHbarAmount.toString()} from ${\n this.kit.userAccountId\n } to ${recipientAccountId.toString()}`\n );\n \n this.addNote(\n `Configured HBAR transfer from your account (${\n this.kit.userAccountId\n }) to ${recipientAccountId.toString()} for ${sdkHbarAmount.toString()}.`\n );\n\n transaction.addHbarTransfer(recipientAccountId, sdkHbarAmount);\n transaction.addHbarTransfer(\n AccountId.fromString(this.kit.userAccountId),\n sdkHbarAmount.negated()\n );\n\n userTransferProcessedForScheduling = true;\n }\n }\n\n if (!userTransferProcessedForScheduling) {\n const processedTransfers: Array<{\n accountId: AccountId;\n amount: BigNumber;\n hbar: Hbar;\n }> = [];\n \n for (const transferInput of params.transfers) {\n const accountId =\n typeof transferInput.accountId === 'string'\n ? AccountId.fromString(transferInput.accountId)\n : transferInput.accountId;\n\n const amountValue =\n typeof transferInput.amount === 'string' ||\n typeof transferInput.amount === 'number'\n ? transferInput.amount\n : transferInput.amount.toString();\n\n const amountBigNum = new BigNumber(amountValue);\n const roundedAmount = amountBigNum.toFixed(8, BigNumber.ROUND_DOWN);\n \n this.logger.info(\n `Processing transfer: ${amountValue} HBAR (rounded to ${roundedAmount}) for account ${accountId.toString()}`\n );\n\n const sdkHbarAmount = Hbar.fromString(roundedAmount);\n processedTransfers.push({\n accountId,\n amount: amountBigNum,\n hbar: sdkHbarAmount\n });\n\n const tinybarsContribution = sdkHbarAmount.toTinybars();\n netZeroInTinybars = netZeroInTinybars.plus(\n tinybarsContribution.toString()\n );\n }\n\n if (!netZeroInTinybars.isZero()) {\n this.logger.warn(\n `Transfer sum not zero: ${netZeroInTinybars.toString()} tinybars off. Adjusting last transfer.`\n );\n \n if (processedTransfers.length > 0) {\n const lastTransfer = processedTransfers[processedTransfers.length - 1];\n const adjustment = netZeroInTinybars.dividedBy(-100000000);\n const adjustedAmount = lastTransfer.amount.plus(adjustment);\n const adjustedRounded = adjustedAmount.toFixed(8, BigNumber.ROUND_DOWN);\n lastTransfer.hbar = Hbar.fromString(adjustedRounded);\n \n this.logger.info(\n `Adjusted last transfer for ${lastTransfer.accountId.toString()} to ${adjustedRounded} HBAR`\n );\n }\n }\n \n for (const transfer of processedTransfers) {\n transaction.addHbarTransfer(transfer.accountId, transfer.hbar);\n }\n }\n\n if (typeof params.memo !== 'undefined') {\n if (params.memo === null) {\n this.logger.warn('Received null for memo in transferHbar.');\n } else {\n transaction.setTransactionMemo(params.memo);\n }\n }\n\n this.setCurrentTransaction(transaction);\n return this;\n }\n}","import { z } from 'zod';\nimport { HbarTransferParams } from './types';\nimport { AccountBuilder } from './AccountBuilder';\nimport { BaseHederaTransactionTool, BaseServiceBuilder } from 'hedera-agent-kit';\n\nconst HbarTransferInputSchema = z.object({\n accountId: z\n .string()\n .describe('Account ID for the transfer (e.g., \"0.0.xxxx\").'),\n amount: z\n .union([z.number(), z.string()])\n .describe(\n 'HBAR amount in decimal format (e.g., 1 for 1 HBAR, 0.5 for 0.5 HBAR). Positive for credit, negative for debit. DO NOT multiply by 10^8 for tinybars - just use the HBAR amount directly.'\n ),\n});\n\nconst TransferHbarZodSchemaCore = z.object({\n transfers: z\n .array(HbarTransferInputSchema)\n .min(1)\n .describe(\n 'Array of transfers. For simple transfers from your operator account, just include the recipient with positive amount: [{accountId: \"0.0.800\", amount: 1}]. For complex multi-party transfers, include all parties with negative amounts for senders and positive for receivers.'\n ),\n memo: z.string().optional().describe('Optional. Memo for the transaction.'),\n});\n\n/**\n * A Hedera transaction tool for transferring HBAR between accounts.\n * Supports single and multi-party transfers with automatic balance validation.\n * Extends BaseHederaTransactionTool to handle HBAR transfer transactions on the Hedera Hashgraph.\n */\nexport class TransferHbarTool extends BaseHederaTransactionTool<\n typeof TransferHbarZodSchemaCore\n> {\n name = 'hedera-account-transfer-hbar-v2';\n description =\n 'PRIMARY TOOL FOR HBAR TRANSFERS: Transfers HBAR between accounts. For simple transfers from the operator account, just specify the recipient with a positive amount (e.g., [{accountId: \"0.0.800\", amount: 1}] to send 1 HBAR to 0.0.800). The sender will be automatically added. For multi-party transfers (e.g., \"A sends 5 HBAR to C and B sends 3 HBAR to C\"), include ALL transfers with their amounts (negative for senders, positive for receivers).';\n specificInputSchema = TransferHbarZodSchemaCore;\n namespace = 'account';\n\n\n /**\n * Creates and returns the service builder for account operations.\n * \n * @returns BaseServiceBuilder instance configured for account operations\n */\n protected getServiceBuilder(): BaseServiceBuilder {\n return new AccountBuilder(this.hederaKit) as BaseServiceBuilder;\n }\n\n /**\n * Executes the HBAR transfer using the provided builder and arguments.\n * Validates that all transfers sum to zero before execution.\n * \n * @param builder - The service builder instance for executing transactions\n * @param specificArgs - The validated transfer parameters including transfers array and optional memo\n * @returns Promise that resolves when the transfer is complete\n */\n protected async callBuilderMethod(\n builder: BaseServiceBuilder,\n specificArgs: z.infer<typeof TransferHbarZodSchemaCore>\n ): Promise<void> {\n await (builder as AccountBuilder).transferHbar(\n specificArgs as unknown as HbarTransferParams\n );\n }\n}","import { StructuredTool } from '@langchain/core/tools';\nimport { z } from 'zod';\nimport { HederaAgentKit } from 'hedera-agent-kit';\nimport { Logger } from '@hashgraphonline/standards-sdk';\n\ninterface TokenInfo {\n decimals: number;\n [key: string]: unknown;\n}\n\ninterface ToolWithCall {\n _call(input: unknown): Promise<string>;\n}\n\ninterface AgentKitWithMirrorNode {\n mirrorNode?: {\n getTokenInfo(tokenId: string): Promise<TokenInfo>;\n };\n network: string;\n}\n\nexport class AirdropToolWrapper extends StructuredTool {\n name = 'hedera-hts-airdrop-token';\n description =\n 'Airdrops fungible tokens to multiple recipients. Automatically converts human-readable amounts to smallest units based on token decimals.';\n\n schema = z.object({\n tokenId: z\n .string()\n .describe('The ID of the fungible token to airdrop (e.g., \"0.0.yyyy\").'),\n recipients: z\n .array(\n z.object({\n accountId: z\n .string()\n .describe('Recipient account ID (e.g., \"0.0.xxxx\").'),\n amount: z\n .union([z.number(), z.string()])\n .describe(\n 'Amount in human-readable format (e.g., \"10\" for 10 tokens).'\n ),\n })\n )\n .min(1)\n .describe('Array of recipient objects, each with accountId and amount.'),\n memo: z.string().optional().describe('Optional. Memo for the transaction.'),\n });\n\n private originalTool: StructuredTool & ToolWithCall;\n private agentKit: HederaAgentKit & AgentKitWithMirrorNode;\n private logger: Logger;\n\n constructor(originalTool: StructuredTool, agentKit: unknown) {\n super();\n this.originalTool = originalTool as StructuredTool & ToolWithCall;\n this.agentKit = agentKit as HederaAgentKit & AgentKitWithMirrorNode;\n this.logger = new Logger({ module: 'AirdropToolWrapper' });\n }\n\n async _call(input: z.infer<typeof this.schema>): Promise<string> {\n try {\n this.logger.info(\n `Processing airdrop request for token ${input.tokenId} with ${input.recipients.length} recipients`\n );\n\n const tokenInfo = await this.getTokenInfo(input.tokenId);\n const decimals = tokenInfo.decimals || 0;\n\n this.logger.info(`Token ${input.tokenId} has ${decimals} decimal places`);\n\n const convertedRecipients = input.recipients.map((recipient) => {\n const humanAmount =\n typeof recipient.amount === 'string'\n ? parseFloat(recipient.amount)\n : recipient.amount;\n const smallestUnitAmount = this.convertToSmallestUnits(\n humanAmount,\n decimals\n );\n\n this.logger.info(\n `Converting amount for ${recipient.accountId}: ${humanAmount} tokens → ${smallestUnitAmount} smallest units`\n );\n\n return {\n ...recipient,\n amount: smallestUnitAmount.toString(),\n };\n });\n\n const convertedInput = {\n ...input,\n recipients: convertedRecipients,\n };\n\n this.logger.info(`Calling original airdrop tool with converted amounts`);\n return await this.originalTool._call(convertedInput);\n } catch (error) {\n this.logger.error('Error in airdrop tool wrapper:', error);\n throw error;\n }\n }\n\n private convertToSmallestUnits(amount: number, decimals: number): number {\n return Math.floor(amount * Math.pow(10, decimals));\n }\n\n private async getTokenInfo(tokenId: string): Promise<TokenInfo> {\n return await this.queryTokenInfo(tokenId);\n }\n\n private async queryTokenInfo(tokenId: string): Promise<TokenInfo> {\n try {\n this.logger.info('Querying token info using mirror node');\n const mirrorNode = this.agentKit.mirrorNode;\n if (!mirrorNode) {\n this.logger.info(\n 'MirrorNode not found in agentKit, attempting to access via fetch'\n );\n const network = this.agentKit.network || 'testnet';\n const mirrorNodeUrl =\n network === 'mainnet'\n ? 'https://mainnet.mirrornode.hedera.com'\n : 'https://testnet.mirrornode.hedera.com';\n\n const response = await fetch(\n `${mirrorNodeUrl}/api/v1/tokens/${tokenId}`\n );\n if (response.ok) {\n const tokenData = (await response.json()) as Record<string, unknown>;\n const decimals = parseInt(String(tokenData.decimals || '0'));\n this.logger.info(\n `Token ${tokenId} found with ${decimals} decimals via API`\n );\n return { ...tokenData, decimals };\n }\n } else {\n const tokenData = await mirrorNode.getTokenInfo(tokenId);\n\n if (tokenData && typeof tokenData.decimals !== 'undefined') {\n const decimals = parseInt(tokenData.decimals.toString()) || 0;\n this.logger.info(`Token ${tokenId} found with ${decimals} decimals`);\n return { ...tokenData, decimals };\n }\n }\n\n throw new Error(`Token data not found or missing decimals field`);\n } catch (error) {\n this.logger.warn(`Failed to query token info for ${tokenId}:`, error);\n\n this.logger.info(\n 'Falling back to assumed 0 decimal places (smallest units)'\n );\n return { decimals: 0 };\n }\n }\n}\n","import {\n GenericPluginContext,\n HederaTool,\n BasePlugin,\n HederaAgentKit,\n HederaAirdropTokenTool,\n} from 'hedera-agent-kit';\nimport { TransferHbarTool } from './TransferHbarTool';\nimport { AirdropToolWrapper } from './AirdropToolWrapper';\nimport { StructuredTool } from '@langchain/core/tools';\n\nexport class HbarPlugin extends BasePlugin {\n id = 'hbar';\n name = 'HBAR Plugin';\n description =\n 'HBAR operations: transfer tool with robust decimal handling and compatibility with airdrop improvements';\n version = '1.0.0';\n author = 'Hashgraph Online';\n namespace = 'account';\n\n private tools: (HederaTool | AirdropToolWrapper)[] = [];\n private originalAirdropTool: StructuredTool | null = null;\n\n override async initialize(context: GenericPluginContext): Promise<void> {\n await super.initialize(context);\n\n const hederaKit = context.config.hederaKit as HederaAgentKit;\n if (!hederaKit) {\n this.context.logger.warn(\n 'HederaKit not found in context. HBAR tools will not be available.'\n );\n return;\n }\n\n try {\n this.initializeTools();\n\n this.context.logger.info('HBAR Plugin initialized successfully');\n } catch (error) {\n this.context.logger.error('Failed to initialize HBAR plugin:', error);\n }\n }\n\n private initializeTools(): void {\n const hederaKit = this.context.config.hederaKit as HederaAgentKit;\n if (!hederaKit) {\n throw new Error('HederaKit not found in context config');\n }\n\n const transfer = new TransferHbarTool({\n hederaKit: hederaKit,\n logger: this.context.logger,\n });\n\n this.tools = [transfer];\n\n try {\n this.context.logger.info(\n 'Creating wrapper for passed original airdrop tool'\n );\n\n const airdropTool = new HederaAirdropTokenTool({\n hederaKit: hederaKit,\n logger: this.context.logger,\n });\n const wrappedAirdropTool = new AirdropToolWrapper(airdropTool, hederaKit);\n this.tools.push(wrappedAirdropTool);\n this.context.logger.info('Added wrapped airdrop tool to HBAR Plugin');\n } catch (error) {\n this.context.logger.error('Error creating airdrop tool wrapper:', error);\n }\n\n this.context.logger.info(\n `HBAR Plugin tools initialized with ${this.tools.length} tools`\n );\n }\n\n override getTools(): HederaTool[] {\n // @ts-ignore\n return this.tools;\n }\n\n async shutdown(): Promise<void> {\n this.tools = [];\n }\n}\n","import { AgentExecutor } from 'langchain/agents';\nimport { Logger } from '@hashgraphonline/standards-sdk';\n\n/**\n * Custom AgentExecutor that intercepts large tool outputs and converts them to content references\n * before they are sent to the LLM to avoid token limit issues.\n * \n * Note: The content reference conversion is already handled in the MCP adapter,\n * so this class currently just extends AgentExecutor without modifications.\n * We keep it as a placeholder for future enhancements.\n */\nexport class ContentAwareAgentExecutor extends AgentExecutor {\n private logger: Logger;\n\n constructor(config: any) {\n super(config);\n this.logger = new Logger({ module: 'ContentAwareAgentExecutor' });\n }\n}","import type { BaseMessage } from '@langchain/core/messages';\nimport type { StructuredTool } from '@langchain/core/tools';\nimport type { TransactionReceipt } from '@hashgraph/sdk';\nimport {\n HederaAgentKit,\n ServerSigner,\n TokenUsageCallbackHandler,\n TokenUsage,\n BasePlugin,\n} from 'hedera-agent-kit';\nimport type { CostCalculation } from 'hedera-agent-kit';\nimport type { AIProvider, VercelAIProvider, BAMLProvider } from './providers';\nimport { Logger } from '@hashgraphonline/standards-sdk';\nimport type { MCPServerConfig, MCPConnectionStatus } from './mcp/types';\n\nexport interface ToolFilterConfig {\n namespaceWhitelist?: string[];\n toolBlacklist?: string[];\n toolPredicate?: (tool: StructuredTool) => boolean;\n}\n\nexport type ExecutionMode = 'direct' | 'bytes';\nexport type OperationalMode = 'autonomous' | 'returnBytes';\n\nexport interface HederaAgentConfiguration {\n signer: ServerSigner;\n execution?: {\n mode?: ExecutionMode;\n operationalMode?: OperationalMode;\n userAccountId?: string;\n scheduleUserTransactions?: boolean;\n scheduleUserTransactionsInBytesMode?: boolean;\n };\n ai?: {\n provider?: AIProvider;\n llm?: unknown;\n apiKey?: string;\n modelName?: string;\n temperature?: number;\n };\n filtering?: ToolFilterConfig;\n messaging?: {\n systemPreamble?: string;\n systemPostamble?: string;\n conciseMode?: boolean;\n };\n extensions?: {\n plugins?: BasePlugin[];\n mirrorConfig?: Record<string, unknown>;\n modelCapability?: string;\n };\n mcp?: {\n servers?: MCPServerConfig[];\n autoConnect?: boolean;\n };\n debug?: {\n verbose?: boolean;\n silent?: boolean;\n };\n}\n\nexport interface ConversationContext {\n messages: BaseMessage[];\n metadata?: Record<string, unknown>;\n}\n\nexport interface ChatResponse {\n output: string;\n message?: string;\n transactionBytes?: string;\n receipt?: TransactionReceipt | object;\n scheduleId?: string;\n transactionId?: string;\n notes?: string[];\n error?: string;\n intermediateSteps?: unknown;\n rawToolOutput?: unknown;\n tokenUsage?: TokenUsage;\n cost?: CostCalculation;\n metadata?: Record<string, unknown>;\n tool_calls?: Array<{\n id: string;\n name: string;\n args: Record<string, unknown>;\n output?: string;\n }>;\n [key: string]: unknown;\n}\n\nexport interface UsageStats extends TokenUsage {\n cost: CostCalculation;\n}\n\nexport abstract class BaseAgent {\n protected logger: Logger;\n protected agentKit: HederaAgentKit | undefined;\n protected tools: StructuredTool[] = [];\n protected initialized = false;\n protected tokenTracker: TokenUsageCallbackHandler | undefined;\n\n constructor(protected config: HederaAgentConfiguration) {\n this.logger = new Logger({\n module: 'BaseAgent',\n silent: config.debug?.silent || false,\n });\n }\n\n abstract boot(): Promise<void>;\n abstract chat(\n message: string,\n context?: ConversationContext\n ): Promise<ChatResponse>;\n abstract shutdown(): Promise<void>;\n abstract switchMode(mode: OperationalMode): void;\n abstract getUsageStats(): UsageStats;\n abstract getUsageLog(): UsageStats[];\n abstract clearUsageStats(): void;\n abstract connectMCPServers(): Promise<void>;\n abstract getMCPConnectionStatus(): Map<string, MCPConnectionStatus>;\n\n public getCore(): HederaAgentKit | undefined {\n return this.agentKit;\n }\n\n protected filterTools(tools: StructuredTool[]): StructuredTool[] {\n let filtered = [...tools];\n const filter = this.config.filtering;\n\n if (!filter) return filtered;\n\n if (filter.namespaceWhitelist?.length) {\n filtered = filtered.filter((tool) => {\n const namespace = (tool as StructuredTool & { namespace?: string })\n .namespace;\n return !namespace || filter.namespaceWhitelist!.includes(namespace);\n });\n }\n\n if (filter.toolBlacklist?.length) {\n filtered = filtered.filter(\n (tool) => !filter.toolBlacklist!.includes(tool.name)\n );\n }\n\n if (filter.toolPredicate) {\n filtered = filtered.filter(filter.toolPredicate);\n }\n\n this.logger.debug(`Filtered tools: ${tools.length} → ${filtered.length}`);\n return filtered;\n }\n\n protected buildSystemPrompt(): string {\n const parts: string[] = [];\n const operatorId = this.config.signer.getAccountId().toString();\n const userAccId = this.config.execution?.userAccountId;\n\n if (this.config.messaging?.systemPreamble) {\n parts.push(this.config.messaging.systemPreamble);\n }\n\n parts.push(\n `You are a helpful Hedera assistant. Your primary operator account is ${operatorId}. ` +\n `You have tools to interact with the Hedera Hashgraph. ` +\n `When using any tool, provide all necessary parameters as defined by that tool's schema and description.`\n );\n\n if (userAccId) {\n parts.push(\n `The user you are assisting has a personal Hedera account ID: ${userAccId}. ` +\n `IMPORTANT: When the user says things like \"I want to send HBAR\" or \"transfer my tokens\", you MUST use ${userAccId} as the sender/from account. ` +\n `For example, if user says \"I want to send 2 HBAR to 0.0.800\", you must set up a transfer where ${userAccId} sends the HBAR, not your operator account.`\n );\n }\n\n const operationalMode =\n this.config.execution?.operationalMode || 'returnBytes';\n if (operationalMode === 'autonomous') {\n parts.push(\n `\\nOPERATIONAL MODE: 'autonomous'. Your goal is to execute transactions directly using your tools. ` +\n `Your account ${operatorId} will be the payer for these transactions. ` +\n `Even if the user's account (${\n userAccId || 'a specified account'\n }) is the actor in the transaction body (e.g., sender of HBAR), ` +\n `you (the agent with operator ${operatorId}) are still executing and paying. For HBAR transfers, ensure the amounts in the 'transfers' array sum to zero (as per tool schema), balancing with your operator account if necessary.`\n );\n } else {\n if (\n this.config.execution?.scheduleUserTransactionsInBytesMode &&\n userAccId\n ) {\n parts.push(\n `\\nOPERATIONAL MODE: 'returnBytes' with scheduled transactions for user actions. ` +\n `When a user asks for a transaction to be prepared (e.g., creating a token, topic, transferring assets for them to sign, etc), ` +\n `you MUST default to creating a Scheduled Transaction using the appropriate tool with the metaOption 'schedule: true'. ` +\n `The user (with account ID ${userAccId}) will be the one to ultimately pay for and (if needed) sign the inner transaction. ` +\n `Your operator account (${operatorId}) will pay for creating the schedule entity itself. ` +\n `You MUST return the ScheduleId and details of the scheduled operation in a structured JSON format with these fields: success, op, schedule_id, description, payer_account_id_scheduled_tx, and scheduled_transaction_details.`\n );\n } else {\n parts.push(\n `\\nOPERATIONAL MODE: 'returnBytes'. Your goal is to provide transaction bytes when possible. ` +\n `When a user asks for a transaction to be prepared (e.g., for them to sign, or for scheduling without the default scheduling flow), ` +\n `you MUST call the appropriate tool. ` +\n `IMPORTANT: Only use metaOption 'returnBytes: true' for tools that explicitly support it (like HBAR transfers, token operations). ` +\n `Many tools (inscriptions, HCS-2, HCS-20, etc.) do NOT support returnBytes and will execute directly - this is expected behavior. ` +\n `For tools without returnBytes support, simply call them with their standard parameters. ` +\n `If you need raw bytes for the user to sign for their own account ${\n userAccId || 'if specified'\n }, ensure the tool constructs the transaction body accordingly when returnBytes IS supported.`\n );\n }\n }\n\n if (this.config.messaging?.conciseMode !== false) {\n parts.push(\n '\\nAlways be concise. If the tool provides a JSON string as its primary output (especially in returnBytes mode), make your accompanying text brief. If the tool does not provide JSON output or an error occurs, your narrative becomes primary; if notes were generated by the tool in such cases, append them to your textual response.'\n );\n }\n\n if (this.config.messaging?.systemPostamble) {\n parts.push(this.config.messaging.systemPostamble);\n }\n\n return parts.join('\\n');\n }\n\n isReady(): boolean {\n return this.initialized;\n }\n}\n\nexport type { AIProvider, VercelAIProvider, BAMLProvider };\n","import type { ContentType, ContentSource } from '../types/content-reference';\nimport type { ContentStorage } from '../memory/ContentStorage';\nimport { Logger } from '@hashgraphonline/standards-sdk';\n\nexport interface MCPResponseContent {\n content: unknown;\n type: 'text' | 'image' | 'resource' | 'text[]' | 'image[]';\n sizeBytes: number;\n mimeType?: string;\n}\n\nexport interface ProcessedResponse {\n content: unknown;\n wasProcessed: boolean;\n referenceCreated?: boolean;\n referenceId?: string;\n originalSize?: number;\n errors?: string[];\n}\n\nexport interface ContentAnalysis {\n shouldProcess: boolean;\n contents: MCPResponseContent[];\n totalSize: number;\n largestContentSize: number;\n}\n\nexport class MCPContentProcessor {\n private contentStorage: ContentStorage;\n private logger: Logger;\n\n constructor(contentStorage: ContentStorage, logger: Logger) {\n this.contentStorage = contentStorage;\n this.logger = logger;\n }\n\n analyzeResponse(response: unknown): ContentAnalysis {\n const contents: MCPResponseContent[] = [];\n let totalSize = 0;\n\n this.extractContentFromResponse(response, contents);\n\n totalSize = contents.reduce((sum, content) => sum + content.sizeBytes, 0);\n const largestContentSize = contents.reduce((max, content) => \n Math.max(max, content.sizeBytes), 0);\n\n const shouldProcess = contents.some(content => \n this.contentStorage.shouldUseReference(\n typeof content.content === 'string' \n ? content.content \n : JSON.stringify(content.content)\n )\n );\n\n return {\n shouldProcess,\n contents,\n totalSize,\n largestContentSize\n };\n }\n\n async processResponse(\n response: unknown,\n serverName: string,\n toolName: string\n ): Promise<ProcessedResponse> {\n try {\n const analysis = this.analyzeResponse(response);\n \n if (!analysis.shouldProcess) {\n return {\n content: response,\n wasProcessed: false\n };\n }\n\n const processedResponse = await this.createReferencedResponse(\n response,\n analysis,\n serverName,\n toolName\n );\n\n return processedResponse;\n } catch (error) {\n this.logger.error('Error processing MCP response:', error);\n return {\n content: response,\n wasProcessed: false,\n errors: [error instanceof Error ? error.message : 'Unknown processing error']\n };\n }\n }\n\n private extractContentFromResponse(obj: unknown, contents: MCPResponseContent[]): void {\n if (obj === null || obj === undefined) {\n return;\n }\n\n if (Array.isArray(obj)) {\n obj.forEach(item => this.extractContentFromResponse(item, contents));\n return;\n }\n\n if (typeof obj === 'object') {\n const record = obj as Record<string, unknown>;\n \n if (record.type === 'text' && typeof record.text === 'string') {\n contents.push({\n content: record.text,\n type: 'text',\n sizeBytes: Buffer.byteLength(record.text, 'utf8'),\n mimeType: this.detectMimeType(record.text as string)\n });\n return;\n }\n\n if (record.type === 'image' && typeof record.data === 'string') {\n contents.push({\n content: record.data,\n type: 'image',\n sizeBytes: Math.ceil(record.data.length * 0.75),\n mimeType: record.mimeType as string || 'image/jpeg'\n });\n return;\n }\n\n if (record.type === 'resource' && record.resource) {\n const resourceStr = JSON.stringify(record.resource);\n contents.push({\n content: resourceStr,\n type: 'resource',\n sizeBytes: Buffer.byteLength(resourceStr, 'utf8'),\n mimeType: 'application/json'\n });\n return;\n }\n\n Object.values(record).forEach(value => \n this.extractContentFromResponse(value, contents));\n return;\n }\n\n if (typeof obj === 'string') {\n if (obj.length > 1000) {\n contents.push({\n content: obj,\n type: 'text',\n sizeBytes: Buffer.byteLength(obj, 'utf8'),\n mimeType: this.detectMimeType(obj)\n });\n }\n }\n }\n\n private async createReferencedResponse(\n originalResponse: unknown,\n analysis: ContentAnalysis,\n serverName: string,\n toolName: string\n ): Promise<ProcessedResponse> {\n const processedResponse = this.deepClone(originalResponse);\n const errors: string[] = [];\n let referenceCreated = false;\n let totalReferenceSize = 0;\n\n for (const contentInfo of analysis.contents) {\n if (this.contentStorage.shouldUseReference(\n typeof contentInfo.content === 'string' \n ? contentInfo.content \n : JSON.stringify(contentInfo.content)\n )) {\n try {\n const contentBuffer = Buffer.from(\n typeof contentInfo.content === 'string' \n ? contentInfo.content \n : JSON.stringify(contentInfo.content),\n 'utf8'\n );\n\n const contentType = this.mapMimeTypeToContentType(contentInfo.mimeType);\n \n const metadata: Parameters<typeof this.contentStorage.storeContentIfLarge>[1] = {\n contentType,\n source: 'mcp_tool' as ContentSource,\n mcpToolName: `${serverName}::${toolName}`,\n tags: ['mcp_response', serverName, toolName]\n };\n \n if (contentInfo.mimeType !== undefined) {\n metadata.mimeType = contentInfo.mimeType;\n }\n \n const reference = await this.contentStorage.storeContentIfLarge(\n contentBuffer,\n metadata\n );\n\n if (reference) {\n this.replaceContentInResponse(\n processedResponse,\n contentInfo.content,\n this.createLightweightReference(reference)\n );\n referenceCreated = true;\n totalReferenceSize += contentBuffer.length;\n }\n } catch (error) {\n errors.push(`Failed to create reference: ${error instanceof Error ? error.message : 'Unknown error'}`);\n }\n }\n }\n\n const result: ProcessedResponse = {\n content: processedResponse,\n wasProcessed: true,\n referenceCreated,\n originalSize: totalReferenceSize\n };\n \n if (errors.length > 0) {\n result.errors = errors;\n }\n \n return result;\n }\n\n private createLightweightReference(reference: any): Record<string, unknown> {\n return {\n type: 'content_reference',\n referenceId: reference.referenceId,\n preview: reference.preview,\n size: reference.metadata.sizeBytes,\n contentType: reference.metadata.contentType,\n format: 'ref://{id}',\n _isReference: true\n };\n }\n\n private replaceContentInResponse(obj: unknown, oldContent: unknown, newContent: any): void {\n if (obj === null || obj === undefined) {\n return;\n }\n\n if (Array.isArray(obj)) {\n for (let i = 0; i < obj.length; i++) {\n if (obj[i] === oldContent) {\n obj[i] = newContent;\n } else {\n this.replaceContentInResponse(obj[i], oldContent, newContent);\n }\n }\n return;\n }\n\n if (typeof obj === 'object') {\n const record = obj as Record<string, unknown>;\n if (record.type === 'text' && record.text === oldContent) {\n for (const key of Object.keys(record)) {\n delete record[key];\n }\n for (const key of Object.keys(newContent)) {\n record[key] = newContent[key];\n }\n return;\n }\n for (const key in record) {\n if (record[key] === oldContent) {\n record[key] = newContent;\n } else {\n this.replaceContentInResponse(record[key], oldContent, newContent);\n }\n }\n }\n }\n\n private detectMimeType(content: string): string {\n if (content.trim().startsWith('{') || content.trim().startsWith('[')) {\n return 'application/json';\n }\n if (content.includes('<html>') || content.includes('<!DOCTYPE')) {\n return 'text/html';\n }\n if (content.includes('# ') || content.includes('## ')) {\n return 'text/markdown';\n }\n return 'text/plain';\n }\n\n private mapMimeTypeToContentType(mimeType?: string): ContentType {\n if (!mimeType) return 'text';\n \n if (mimeType.startsWith('text/plain')) return 'text';\n if (mimeType === 'application/json') return 'json';\n if (mimeType === 'text/html') return 'html';\n if (mimeType === 'text/markdown') return 'markdown';\n if (mimeType.startsWith('text/')) return 'text';\n \n return 'binary';\n }\n\n private deepClone<T>(obj: T): T {\n if (obj === null || typeof obj !== 'object') {\n return obj;\n }\n \n if (obj instanceof Date) {\n return new Date(obj.getTime()) as T;\n }\n \n if (Array.isArray(obj)) {\n return obj.map(item => this.deepClone(item)) as T;\n }\n \n const cloned = {} as T;\n for (const key in obj) {\n if (obj.hasOwnProperty(key)) {\n cloned[key] = this.deepClone(obj[key]);\n }\n }\n \n return cloned;\n }\n}","import { Client } from '@modelcontextprotocol/sdk/client/index.js';\nimport { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';\nimport type { MCPServerConfig, MCPToolInfo, MCPConnectionStatus } from './types';\nimport { Logger } from '@hashgraphonline/standards-sdk';\nimport type { ContentStorage } from '../memory/ContentStorage';\nimport { MCPContentProcessor, ProcessedResponse } from './ContentProcessor';\n\n/**\n * Manages connections to MCP servers and tool discovery\n */\nexport class MCPClientManager {\n private clients: Map<string, Client> = new Map();\n private tools: Map<string, MCPToolInfo[]> = new Map();\n private logger: Logger;\n private contentProcessor?: MCPContentProcessor;\n\n constructor(logger: Logger, contentStorage?: ContentStorage) {\n this.logger = logger;\n if (contentStorage) {\n this.contentProcessor = new MCPContentProcessor(contentStorage, logger);\n }\n }\n\n /**\n * Connect to an MCP server and discover its tools\n */\n async connectServer(config: MCPServerConfig): Promise<MCPConnectionStatus> {\n try {\n if (this.isServerConnected(config.name)) {\n return {\n serverName: config.name,\n connected: false,\n error: `Server ${config.name} is already connected`,\n tools: [],\n };\n }\n\n if (config.transport && config.transport !== 'stdio') {\n throw new Error(`Transport ${config.transport} not yet supported`);\n }\n\n const transport = new StdioClientTransport({\n command: config.command,\n args: config.args,\n ...(config.env && { env: config.env }),\n });\n\n const client = new Client({\n name: `conversational-agent-${config.name}`,\n version: '1.0.0',\n }, {\n capabilities: {},\n });\n\n await client.connect(transport);\n this.clients.set(config.name, client);\n\n const toolsResponse = await client.listTools();\n const toolsWithServer: MCPToolInfo[] = toolsResponse.tools.map(tool => ({\n ...tool,\n serverName: config.name,\n }));\n\n this.tools.set(config.name, toolsWithServer);\n this.logger.info(`Connected to MCP server ${config.name} with ${toolsWithServer.length} tools`);\n\n return {\n serverName: config.name,\n connected: true,\n tools: toolsWithServer,\n };\n } catch (error) {\n this.logger.error(`Failed to connect to MCP server ${config.name}:`, error);\n return {\n serverName: config.name,\n connected: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n tools: [],\n };\n }\n }\n\n /**\n * Execute a tool on a specific MCP server\n */\n async executeTool(serverName: string, toolName: string, args: Record<string, unknown>): Promise<unknown> {\n const client = this.clients.get(serverName);\n if (!client) {\n throw new Error(`MCP server ${serverName} not connected`);\n }\n\n this.logger.debug(`Executing MCP tool ${toolName} on server ${serverName}`, args);\n\n try {\n const result = await client.callTool({\n name: toolName,\n arguments: args,\n });\n\n if (this.contentProcessor) {\n const processed = await this.contentProcessor.processResponse(result, serverName, toolName);\n \n if (processed.wasProcessed) {\n this.logger.debug(\n `Processed MCP response from ${serverName}::${toolName}`,\n {\n referenceCreated: processed.referenceCreated,\n originalSize: processed.originalSize,\n errors: processed.errors\n }\n );\n\n if (processed.errors && processed.errors.length > 0) {\n this.logger.warn(`Content processing warnings for ${serverName}::${toolName}:`, processed.errors);\n }\n }\n\n return processed.content;\n }\n\n return result;\n } catch (error) {\n this.logger.error(`Error executing MCP tool ${toolName}:`, error);\n throw error;\n }\n }\n\n /**\n * Disconnect all MCP servers\n */\n async disconnectAll(): Promise<void> {\n for (const [name, client] of this.clients) {\n try {\n await client.close();\n this.logger.info(`Disconnected from MCP server ${name}`);\n } catch (error) {\n this.logger.error(`Error disconnecting MCP server ${name}:`, error);\n }\n }\n this.clients.clear();\n this.tools.clear();\n }\n\n /**\n * Get all discovered tools from all connected servers\n */\n getAllTools(): MCPToolInfo[] {\n const allTools: MCPToolInfo[] = [];\n for (const tools of this.tools.values()) {\n allTools.push(...tools);\n }\n return allTools;\n }\n\n /**\n * Get tools from a specific server\n */\n getServerTools(serverName: string): MCPToolInfo[] {\n return this.tools.get(serverName) || [];\n }\n\n /**\n * Check if a server is connected\n */\n isServerConnected(serverName: string): boolean {\n return this.clients.has(serverName);\n }\n\n /**\n * Get list of connected server names\n */\n getConnectedServers(): string[] {\n return Array.from(this.clients.keys());\n }\n\n /**\n * Enable content processing with content storage\n */\n enableContentProcessing(contentStorage: ContentStorage): void {\n this.contentProcessor = new MCPContentProcessor(contentStorage, this.logger);\n this.logger.info('Content processing enabled for MCP responses');\n }\n\n /**\n * Disable content processing\n */\n disableContentProcessing(): void {\n delete this.contentProcessor;\n this.logger.info('Content processing disabled for MCP responses');\n }\n\n /**\n * Check if content processing is enabled\n */\n isContentProcessingEnabled(): boolean {\n return this.contentProcessor !== undefined;\n }\n\n /**\n * Analyze a response without processing it (for testing/debugging)\n */\n analyzeResponseContent(response: unknown): unknown {\n if (!this.contentProcessor) {\n throw new Error('Content processing is not enabled');\n }\n return this.contentProcessor.analyzeResponse(response);\n }\n}","import { DynamicStructuredTool } from '@langchain/core/tools';\nimport { z } from 'zod';\nimport type { MCPToolInfo, MCPServerConfig } from '../types';\nimport type { MCPClientManager } from '../MCPClientManager';\nimport { ContentStoreService, shouldUseReference } from '@hashgraphonline/standards-sdk';\nimport type { ContentSource } from '../../types/content-reference';\n\n/**\n * Convert an MCP tool to a LangChain DynamicStructuredTool\n */\nexport function convertMCPToolToLangChain(\n tool: MCPToolInfo,\n mcpManager: MCPClientManager,\n serverConfig?: MCPServerConfig\n): DynamicStructuredTool {\n const zodSchema = jsonSchemaToZod(tool.inputSchema);\n\n const sanitizedName = `${tool.serverName}_${tool.name}`.replace(\n /[^a-zA-Z0-9_]/g,\n '_'\n );\n\n let description = tool.description || `MCP tool ${tool.name} from ${tool.serverName}`;\n \n if (serverConfig?.toolDescriptions?.[tool.name]) {\n description = `${description}\\n\\n${serverConfig.toolDescriptions[tool.name]}`;\n }\n \n if (serverConfig?.additionalContext) {\n description = `${description}\\n\\nContext: ${serverConfig.additionalContext}`;\n }\n\n return new DynamicStructuredTool({\n name: sanitizedName,\n description,\n schema: zodSchema,\n func: async (input) => {\n try {\n const result = await mcpManager.executeTool(\n tool.serverName,\n tool.name,\n input\n );\n\n let responseText = '';\n \n if (typeof result === 'string') {\n responseText = result;\n } else if (\n result &&\n typeof result === 'object' &&\n 'content' in result\n ) {\n const content = (result as { content: unknown }).content;\n if (Array.isArray(content)) {\n const textParts = content\n .filter(\n (item): item is { type: string; text: string } =>\n typeof item === 'object' &&\n item !== null &&\n 'type' in item &&\n item.type === 'text' &&\n 'text' in item\n )\n .map((item) => item.text);\n responseText = textParts.join('\\n');\n } else {\n responseText = JSON.stringify(content);\n }\n } else {\n responseText = JSON.stringify(result);\n }\n\n const responseBuffer = Buffer.from(responseText, 'utf8');\n \n const MCP_REFERENCE_THRESHOLD = 10 * 1024;\n const shouldStoreMCPContent = responseBuffer.length > MCP_REFERENCE_THRESHOLD;\n \n if (shouldStoreMCPContent || shouldUseReference(responseBuffer)) {\n const contentStore = ContentStoreService.getInstance();\n if (contentStore) {\n try {\n const referenceId = await contentStore.storeContent(responseBuffer, {\n contentType: 'text' as ContentSource,\n source: 'mcp',\n mcpToolName: `${tool.serverName}_${tool.name}`,\n originalSize: responseBuffer.length\n });\n return `content-ref:${referenceId}`;\n } catch (storeError) {\n }\n }\n }\n\n return responseText;\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : 'Unknown error';\n return `Error executing MCP tool ${tool.name}: ${errorMessage}`;\n }\n },\n });\n}\n\n/**\n * Convert JSON Schema to Zod schema\n * This is a simplified converter that handles common cases\n */\nfunction jsonSchemaToZod(schema: unknown): z.ZodTypeAny {\n if (!schema || typeof schema !== 'object') {\n return z.object({});\n }\n\n const schemaObj = schema as Record<string, unknown>;\n\n if (schemaObj.type && schemaObj.type !== 'object') {\n return convertType(schemaObj);\n }\n\n if (!schemaObj.properties || typeof schemaObj.properties !== 'object') {\n return z.object({});\n }\n\n const shape: Record<string, z.ZodTypeAny> = {};\n\n for (const [key, value] of Object.entries(schemaObj.properties)) {\n let zodType = convertType(value);\n\n const isRequired =\n Array.isArray(schemaObj.required) && schemaObj.required.includes(key);\n if (!isRequired) {\n zodType = zodType.optional();\n }\n\n shape[key] = zodType;\n }\n\n return z.object(shape);\n}\n\n/**\n * Convert a single JSON Schema type to Zod\n */\nfunction convertType(schema: unknown): z.ZodTypeAny {\n if (!schema || typeof schema !== 'object' || !('type' in schema)) {\n return z.unknown();\n }\n\n const schemaObj = schema as {\n type: string;\n enum?: unknown[];\n items?: unknown;\n };\n let zodType: z.ZodTypeAny;\n\n switch (schemaObj.type) {\n case 'string':\n zodType = z.string();\n if (schemaObj.enum && Array.isArray(schemaObj.enum)) {\n zodType = z.enum(schemaObj.enum as [string, ...string[]]);\n }\n break;\n\n case 'number':\n zodType = z.number();\n if ('minimum' in schemaObj && typeof schemaObj.minimum === 'number') {\n zodType = (zodType as z.ZodNumber).min(schemaObj.minimum);\n }\n if ('maximum' in schemaObj && typeof schemaObj.maximum === 'number') {\n zodType = (zodType as z.ZodNumber).max(schemaObj.maximum);\n }\n break;\n\n case 'integer':\n zodType = z.number().int();\n if ('minimum' in schemaObj && typeof schemaObj.minimum === 'number') {\n zodType = (zodType as z.ZodNumber).min(schemaObj.minimum);\n }\n if ('maximum' in schemaObj && typeof schemaObj.maximum === 'number') {\n zodType = (zodType as z.ZodNumber).max(schemaObj.maximum);\n }\n break;\n\n case 'boolean':\n zodType = z.boolean();\n break;\n\n case 'array':\n if (schemaObj.items) {\n zodType = z.array(convertType(schemaObj.items));\n } else {\n zodType = z.array(z.unknown());\n }\n break;\n\n case 'object':\n if ('properties' in schemaObj) {\n zodType = jsonSchemaToZod(schemaObj);\n } else {\n zodType = z.object({}).passthrough();\n }\n break;\n\n default:\n zodType = z.unknown();\n }\n\n if ('description' in schemaObj && typeof schemaObj.description === 'string') {\n zodType = zodType.describe(schemaObj.description);\n }\n\n return zodType;\n}\n","import { encoding_for_model } from 'tiktoken';\nimport type { TiktokenModel } from 'tiktoken';\nimport type { BaseMessage } from '@langchain/core/messages';\n\n/**\n * Token counter utility for OpenAI models using tiktoken encoding\n * Provides accurate token counting for text content and chat messages\n */\nexport class TokenCounter {\n private encoding: ReturnType<typeof encoding_for_model>;\n private modelName: string;\n\n private static readonly MESSAGE_OVERHEAD = 3;\n private static readonly ROLE_OVERHEAD = 1;\n\n constructor(modelName: string | TiktokenModel = 'gpt-4o') {\n this.modelName = String(modelName);\n try {\n this.encoding = encoding_for_model(modelName as TiktokenModel);\n } catch {\n this.encoding = encoding_for_model('gpt-4o');\n this.modelName = 'gpt-4o';\n }\n }\n\n /**\n * Count tokens in raw text content\n * @param text - The text to count tokens for\n * @returns Number of tokens\n */\n countTokens(text: string): number {\n if (!text || text.trim() === '') {\n return 0;\n }\n\n try {\n const tokens = this.encoding.encode(text);\n return tokens.length;\n } catch (error) {\n return Math.ceil(text.split(/\\s+/).length * 1.3);\n }\n }\n\n /**\n * Count tokens for a single chat message including role overhead\n * @param message - The message to count tokens for\n * @returns Number of tokens including message formatting overhead\n */\n countMessageTokens(message: BaseMessage): number {\n const contentTokens = this.countTokens(String(message.content ?? ''));\n const roleTokens = this.countTokens(this.getMessageRole(message));\n \n return contentTokens + roleTokens + TokenCounter.MESSAGE_OVERHEAD + TokenCounter.ROLE_OVERHEAD;\n }\n\n /**\n * Count tokens for multiple messages\n * @param messages - Array of messages to count\n * @returns Total token count for all messages\n */\n countMessagesTokens(messages: BaseMessage[]): number {\n if (!messages || messages.length === 0) {\n return 0;\n }\n\n let total = 0;\n for (const message of messages) {\n total += this.countMessageTokens(message);\n }\n return total;\n }\n\n /**\n * Estimate tokens for system prompt\n * System prompts have slightly different overhead in chat completions\n * @param systemPrompt - The system prompt text\n * @returns Estimated token count\n */\n estimateSystemPromptTokens(systemPrompt: string): number {\n if (!systemPrompt || systemPrompt.trim() === '') {\n return 0;\n }\n\n const contentTokens = this.countTokens(systemPrompt);\n const roleTokens = this.countTokens('system');\n \n return contentTokens + roleTokens + TokenCounter.MESSAGE_OVERHEAD + TokenCounter.ROLE_OVERHEAD;\n }\n\n /**\n * Get total context size estimate including system prompt and messages\n * @param systemPrompt - System prompt text\n * @param messages - Conversation messages\n * @returns Total estimated token count\n */\n estimateContextSize(systemPrompt: string, messages: BaseMessage[]): number {\n const systemTokens = this.estimateSystemPromptTokens(systemPrompt);\n const messageTokens = this.countMessagesTokens(messages);\n \n const completionOverhead = 10;\n \n return systemTokens + messageTokens + completionOverhead;\n }\n\n /**\n * Get the role string for a message\n * @param message - The message to get the role for\n * @returns Role string ('user', 'assistant', 'system', etc.)\n */\n private getMessageRole(message: BaseMessage): string {\n const messageType = message._getType();\n switch (messageType) {\n case 'human':\n return 'user';\n case 'ai':\n return 'assistant';\n case 'system':\n return 'system';\n case 'function':\n return 'function';\n case 'tool':\n return 'tool';\n default:\n return 'user';\n }\n }\n\n /**\n * Get the model name being used for token counting\n * @returns The tiktoken model name\n */\n getModelName(): string {\n return this.modelName;\n }\n\n /**\n * Clean up encoding resources\n */\n dispose(): void {\n try {\n this.encoding.free();\n } catch {\n }\n }\n}","import type { BaseMessage } from '@langchain/core/messages';\nimport { TokenCounter } from './TokenCounter';\n\n/**\n * Result of adding a message to the memory window\n */\nexport interface AddMessageResult {\n /** Whether the message was successfully added */\n added: boolean;\n /** Messages that were pruned to make room */\n prunedMessages: BaseMessage[];\n /** Current token count after operation */\n currentTokenCount: number;\n /** Remaining token capacity */\n remainingCapacity: number;\n}\n\n/**\n * Memory window that manages conversation history with token-based size limits\n * Automatically prunes old messages to stay within token limits while preserving conversational context\n */\nexport class MemoryWindow {\n private messages: BaseMessage[] = [];\n private maxTokens: number;\n private reserveTokens: number;\n private tokenCounter: TokenCounter;\n private systemPrompt: string = '';\n private systemPromptTokens: number = 0;\n\n public static readonly DEFAULT_MAX_TOKENS = 8000;\n public static readonly DEFAULT_RESERVE_TOKENS = 1000;\n public static readonly PRUNING_BATCH_SIZE = 2;\n\n constructor(\n maxTokens: number = MemoryWindow.DEFAULT_MAX_TOKENS,\n reserveTokens: number = MemoryWindow.DEFAULT_RESERVE_TOKENS,\n tokenCounter?: TokenCounter\n ) {\n if (reserveTokens >= maxTokens) {\n throw new Error('Reserve tokens must be less than max tokens');\n }\n\n this.maxTokens = maxTokens;\n this.reserveTokens = reserveTokens;\n this.tokenCounter = tokenCounter || new TokenCounter();\n }\n\n /**\n * Add a message to the memory window, pruning old messages if necessary\n * @param message - The message to add\n * @returns Result of the add operation including any pruned messages\n */\n addMessage(message: BaseMessage): AddMessageResult {\n this.tokenCounter.countMessageTokens(message);\n \n this.messages.push(message);\n \n const currentTokens = this.getCurrentTokenCount();\n const availableTokens = this.maxTokens - this.reserveTokens;\n \n let prunedMessages: BaseMessage[] = [];\n \n if (currentTokens > availableTokens) {\n this.messages.pop();\n \n prunedMessages = this.pruneToFit();\n \n this.messages.push(message);\n }\n\n return {\n added: true,\n prunedMessages,\n currentTokenCount: this.getCurrentTokenCount(),\n remainingCapacity: this.getRemainingTokenCapacity()\n };\n }\n\n /**\n * Prune old messages to fit within token limits\n * Removes messages in pairs to maintain conversational flow\n * @returns Array of pruned messages\n */\n pruneToFit(): BaseMessage[] {\n const prunedMessages: BaseMessage[] = [];\n const targetTokens = this.maxTokens - this.reserveTokens;\n \n while (this.getCurrentTokenCount() > targetTokens && this.messages.length > 0) {\n const batchSize = Math.min(MemoryWindow.PRUNING_BATCH_SIZE, this.messages.length);\n \n for (let i = 0; i < batchSize; i++) {\n const prunedMessage = this.messages.shift();\n if (prunedMessage) {\n prunedMessages.push(prunedMessage);\n }\n }\n \n if (prunedMessages.length > 1000) {\n break;\n }\n }\n\n return prunedMessages;\n }\n\n /**\n * Get current token count including system prompt and messages\n * @returns Current token count\n */\n getCurrentTokenCount(): number {\n const messageTokens = this.tokenCounter.countMessagesTokens(this.messages);\n return this.systemPromptTokens + messageTokens;\n }\n\n /**\n * Get remaining token capacity before hitting the reserve limit\n * @returns Remaining tokens that can be used\n */\n getRemainingTokenCapacity(): number {\n return Math.max(0, this.maxTokens - this.getCurrentTokenCount());\n }\n\n /**\n * Check if a message can be added without exceeding limits\n * @param message - The message to check\n * @returns True if message can be added within reserve limits\n */\n canAddMessage(message: BaseMessage): boolean {\n const messageTokens = this.tokenCounter.countMessageTokens(message);\n const currentTokens = this.getCurrentTokenCount();\n const wouldExceedReserve = (currentTokens + messageTokens) > (this.maxTokens - this.reserveTokens);\n \n if (messageTokens > this.maxTokens) {\n return false;\n }\n \n return !wouldExceedReserve || this.messages.length > 0;\n }\n\n /**\n * Get all messages in the memory window\n * @returns Copy of current messages array\n */\n getMessages(): BaseMessage[] {\n return [...this.messages];\n }\n\n /**\n * Clear all messages from the memory window\n */\n clear(): void {\n this.messages = [];\n }\n\n /**\n * Set the system prompt and update token calculations\n * @param systemPrompt - The system prompt text\n */\n setSystemPrompt(systemPrompt: string): void {\n this.systemPrompt = systemPrompt;\n this.systemPromptTokens = this.tokenCounter.estimateSystemPromptTokens(systemPrompt);\n }\n\n /**\n * Get the current system prompt\n * @returns Current system prompt\n */\n getSystemPrompt(): string {\n return this.systemPrompt;\n }\n\n /**\n * Get current configuration\n * @returns Memory window configuration\n */\n getConfig() {\n return {\n maxTokens: this.maxTokens,\n reserveTokens: this.reserveTokens,\n currentTokens: this.getCurrentTokenCount(),\n messageCount: this.messages.length,\n systemPromptTokens: this.systemPromptTokens\n };\n }\n\n /**\n * Update token limits\n * @param maxTokens - New maximum token limit\n * @param reserveTokens - New reserve token amount\n */\n updateLimits(maxTokens: number, reserveTokens?: number): void {\n if (reserveTokens !== undefined && reserveTokens >= maxTokens) {\n throw new Error('Reserve tokens must be less than max tokens');\n }\n\n this.maxTokens = maxTokens;\n if (reserveTokens !== undefined) {\n this.reserveTokens = reserveTokens;\n }\n\n if (this.getCurrentTokenCount() > (this.maxTokens - this.reserveTokens)) {\n this.pruneToFit();\n }\n }\n\n /**\n * Get statistics about the memory window\n * @returns Memory usage statistics\n */\n getStats() {\n const currentTokens = this.getCurrentTokenCount();\n const capacity = this.maxTokens;\n const usagePercentage = (currentTokens / capacity) * 100;\n \n return {\n totalMessages: this.messages.length,\n currentTokens,\n maxTokens: capacity,\n reserveTokens: this.reserveTokens,\n systemPromptTokens: this.systemPromptTokens,\n usagePercentage: Math.round(usagePercentage * 100) / 100,\n remainingCapacity: this.getRemainingTokenCapacity(),\n canAcceptMore: this.getRemainingTokenCapacity() > this.reserveTokens\n };\n }\n\n /**\n * Clean up resources\n */\n dispose(): void {\n this.clear();\n this.tokenCounter.dispose();\n }\n}","import { createHash } from 'crypto';\nimport { ReferenceId } from '../types/content-reference';\n\n/**\n * Content-based reference ID generator using SHA-256 (HCS-1 style)\n * \n * Generates deterministic reference IDs based on content hashing.\n * Same content always produces the same reference ID.\n */\nexport class ReferenceIdGenerator {\n /**\n * Generate a content-based reference ID using SHA-256 hashing\n * \n * @param content The content to generate a reference ID for\n * @returns Deterministic reference ID based on content hash\n */\n static generateId(content: Buffer): ReferenceId {\n const hash = createHash('sha256');\n hash.update(content);\n return hash.digest('hex');\n }\n \n /**\n * Validate that a string is a properly formatted reference ID\n * \n * @param id The ID to validate\n * @returns true if the ID is valid format\n */\n static isValidReferenceId(id: string): id is ReferenceId {\n if (!id || typeof id !== 'string') {\n return false;\n }\n \n if (id.length !== 64) {\n return false;\n }\n \n return /^[a-f0-9]+$/.test(id);\n }\n \n /**\n * Extract reference ID from ref:// format\n * \n * @param input Input string that may contain a reference ID\n * @returns Extracted reference ID or null if not found\n */\n static extractReferenceId(input: string): ReferenceId | null {\n if (!input || typeof input !== 'string') {\n return null;\n }\n \n const refFormatMatch = input.match(/^ref:\\/\\/([a-f0-9]{64})$/);\n if (refFormatMatch) {\n return refFormatMatch[1] as ReferenceId;\n }\n \n return this.isValidReferenceId(input) ? input : null;\n }\n \n /**\n * Format a reference ID in the standard ref:// format\n * \n * @param referenceId The reference ID to format\n * @returns Formatted reference string\n */\n static formatReference(referenceId: ReferenceId): string {\n return `ref://${referenceId}`;\n }\n \n /**\n * Generate a test reference ID (for testing purposes only)\n * \n * @param testSeed A test seed to generate a fake but valid ID format\n * @returns A valid format reference ID for testing\n */\n static generateTestId(testSeed: string): ReferenceId {\n const content = Buffer.from(`test-${testSeed}-${Date.now()}`);\n return this.generateId(content);\n }\n}","/**\n * Content Reference System Types\n * \n * Shared interfaces for the Reference-Based Content System that handles\n * large content storage with unique reference IDs to optimize context window usage.\n */\n\n/**\n * Unique identifier for stored content references\n * Format: Cryptographically secure 32-byte identifier with base64url encoding\n */\nexport type ReferenceId = string;\n\n/**\n * Lifecycle state of a content reference\n */\nexport type ReferenceLifecycleState = 'active' | 'expired' | 'cleanup_pending' | 'invalid';\n\n/**\n * Content types supported by the reference system\n */\nexport type ContentType = 'text' | 'json' | 'html' | 'markdown' | 'binary' | 'unknown';\n\n/**\n * Sources that created the content reference\n */\nexport type ContentSource = 'mcp_tool' | 'user_upload' | 'agent_generated' | 'system';\n\n/**\n * Metadata associated with stored content\n */\nexport interface ContentMetadata {\n /** Content type classification */\n contentType: ContentType;\n \n /** MIME type of the original content */\n mimeType?: string;\n \n /** Size in bytes of the stored content */\n sizeBytes: number;\n \n /** When the content was originally stored */\n createdAt: Date;\n \n /** Last time the content was accessed via reference resolution */\n lastAccessedAt: Date;\n \n /** Source that created this content reference */\n source: ContentSource;\n \n /** Name of the MCP tool that generated the content (if applicable) */\n mcpToolName?: string;\n \n /** Original filename or suggested name for the content */\n fileName?: string;\n \n /** Number of times this reference has been resolved */\n accessCount: number;\n \n /** Tags for categorization and cleanup policies */\n tags?: string[];\n \n /** Custom metadata from the source */\n customMetadata?: Record<string, unknown>;\n}\n\n/**\n * Core content reference object passed through agent context\n * Designed to be lightweight (<100 tokens) while providing enough \n * information for agent decision-making\n */\nexport interface ContentReference {\n /** Unique identifier for resolving the content */\n referenceId: ReferenceId;\n \n /** Current lifecycle state */\n state: ReferenceLifecycleState;\n \n /** Brief description or preview of the content (max 200 chars) */\n preview: string;\n \n /** Essential metadata for agent decision-making */\n metadata: Pick<ContentMetadata, 'contentType' | 'sizeBytes' | 'source' | 'fileName' | 'mimeType'>;\n \n /** When this reference was created */\n createdAt: Date;\n \n /** Special format indicator for reference IDs in content */\n readonly format: 'ref://{id}';\n}\n\n/**\n * Result of attempting to resolve a content reference\n */\nexport interface ReferenceResolutionResult {\n /** Whether the resolution was successful */\n success: boolean;\n \n /** The resolved content if successful */\n content?: Buffer;\n \n /** Complete metadata if successful */\n metadata?: ContentMetadata;\n \n /** Error message if resolution failed */\n error?: string;\n \n /** Specific error type for targeted error handling */\n errorType?: 'not_found' | 'expired' | 'corrupted' | 'access_denied' | 'system_error';\n \n /** Suggested actions for recovery */\n suggestedActions?: string[];\n}\n\n/**\n * Configuration for content reference storage and lifecycle\n */\nexport interface ContentReferenceConfig {\n /** Size threshold above which content should be stored as references (default: 10KB) */\n sizeThresholdBytes: number;\n \n /** Maximum age for unused references before cleanup (default: 1 hour) */\n maxAgeMs: number;\n \n /** Maximum number of references to store simultaneously */\n maxReferences: number;\n \n /** Maximum total storage size for all references */\n maxTotalStorageBytes: number;\n \n /** Whether to enable automatic cleanup */\n enableAutoCleanup: boolean;\n \n /** Interval for cleanup checks in milliseconds */\n cleanupIntervalMs: number;\n \n /** Whether to persist references across restarts */\n enablePersistence: boolean;\n \n /** Storage backend configuration */\n storageBackend: 'memory' | 'filesystem' | 'hybrid';\n \n /** Cleanup policies for different content types */\n cleanupPolicies: {\n /** Policy for content marked as \"recent\" from MCP tools */\n recent: { maxAgeMs: number; priority: number };\n \n /** Policy for user-uploaded content */\n userContent: { maxAgeMs: number; priority: number };\n \n /** Policy for agent-generated content */\n agentGenerated: { maxAgeMs: number; priority: number };\n \n /** Default policy for other content */\n default: { maxAgeMs: number; priority: number };\n };\n}\n\n/**\n * Default configuration values\n */\nexport const DEFAULT_CONTENT_REFERENCE_CONFIG: ContentReferenceConfig = {\n sizeThresholdBytes: 10 * 1024,\n maxAgeMs: 60 * 60 * 1000,\n maxReferences: 100,\n maxTotalStorageBytes: 100 * 1024 * 1024,\n enableAutoCleanup: true,\n cleanupIntervalMs: 5 * 60 * 1000,\n enablePersistence: false,\n storageBackend: 'memory',\n cleanupPolicies: {\n recent: { maxAgeMs: 30 * 60 * 1000, priority: 1 },\n userContent: { maxAgeMs: 2 * 60 * 60 * 1000, priority: 2 },\n agentGenerated: { maxAgeMs: 60 * 60 * 1000, priority: 3 },\n default: { maxAgeMs: 60 * 60 * 1000, priority: 4 }\n }\n};\n\n/**\n * Statistics about content reference usage and storage\n */\nexport interface ContentReferenceStats {\n /** Total number of active references */\n activeReferences: number;\n \n /** Total storage used by all references in bytes */\n totalStorageBytes: number;\n \n /** Number of references cleaned up in last cleanup cycle */\n recentlyCleanedUp: number;\n \n /** Number of successful reference resolutions since startup */\n totalResolutions: number;\n \n /** Number of failed resolution attempts */\n failedResolutions: number;\n \n /** Average content size in bytes */\n averageContentSize: number;\n \n /** Most frequently accessed reference ID */\n mostAccessedReferenceId?: ReferenceId;\n \n /** Storage utilization percentage */\n storageUtilization: number;\n \n /** Performance metrics */\n performanceMetrics: {\n /** Average time to create a reference in milliseconds */\n averageCreationTimeMs: number;\n \n /** Average time to resolve a reference in milliseconds */\n averageResolutionTimeMs: number;\n \n /** Average cleanup time in milliseconds */\n averageCleanupTimeMs: number;\n };\n}\n\n/**\n * Error types for content reference operations\n */\nexport class ContentReferenceError extends Error {\n constructor(\n message: string,\n public readonly type: ReferenceResolutionResult['errorType'],\n public readonly referenceId?: ReferenceId,\n public readonly suggestedActions?: string[]\n ) {\n super(message);\n this.name = 'ContentReferenceError';\n }\n}\n\n/**\n * Interface for content reference storage implementations\n */\nexport interface ContentReferenceStore {\n /**\n * Store content and return a reference\n */\n storeContent(\n content: Buffer,\n metadata: Omit<ContentMetadata, 'createdAt' | 'lastAccessedAt' | 'accessCount'>\n ): Promise<ContentReference>;\n \n /**\n * Resolve a reference to its content\n */\n resolveReference(referenceId: ReferenceId): Promise<ReferenceResolutionResult>;\n \n /**\n * Check if a reference exists and is valid\n */\n hasReference(referenceId: ReferenceId): Promise<boolean>;\n \n /**\n * Mark a reference for cleanup\n */\n cleanupReference(referenceId: ReferenceId): Promise<boolean>;\n \n /**\n * Get current storage statistics\n */\n getStats(): Promise<ContentReferenceStats>;\n \n /**\n * Update configuration\n */\n updateConfig(config: Partial<ContentReferenceConfig>): Promise<void>;\n \n /**\n * Perform cleanup based on current policies\n */\n performCleanup(): Promise<{ cleanedUp: number; errors: string[] }>;\n \n /**\n * Dispose of resources\n */\n dispose(): Promise<void>;\n}","import type { BaseMessage } from '@langchain/core/messages';\nimport { ReferenceIdGenerator } from './ReferenceIdGenerator';\nimport {\n ReferenceId,\n ContentReference,\n ContentMetadata,\n ReferenceResolutionResult,\n ContentReferenceConfig,\n ContentReferenceStore,\n ContentReferenceStats,\n ContentReferenceError,\n ContentType,\n ContentSource,\n ReferenceLifecycleState,\n DEFAULT_CONTENT_REFERENCE_CONFIG\n} from '../types/content-reference';\n\n/**\n * Stored message with metadata\n */\ninterface StoredMessage {\n message: BaseMessage;\n storedAt: Date;\n id: string;\n}\n\n/**\n * Search options for message queries\n */\ninterface SearchOptions {\n /** Whether to perform case-sensitive search */\n caseSensitive?: boolean;\n /** Maximum number of results to return */\n limit?: number;\n /** Whether to use regex pattern matching */\n useRegex?: boolean;\n}\n\n/**\n * Result of storing messages\n */\ninterface StoreResult {\n /** Number of messages successfully stored */\n stored: number;\n /** Number of old messages dropped to make room */\n dropped: number;\n}\n\n/**\n * Storage statistics\n */\nexport interface StorageStats {\n /** Total number of messages currently stored */\n totalMessages: number;\n /** Maximum storage capacity */\n maxStorageLimit: number;\n /** Percentage of storage used */\n usagePercentage: number;\n /** Timestamp of oldest message */\n oldestMessageTime: Date | undefined;\n /** Timestamp of newest message */\n newestMessageTime: Date | undefined;\n}\n\n/**\n * Stored content with reference metadata\n */\ninterface StoredContent {\n /** The actual content buffer */\n content: Buffer;\n \n /** Complete metadata */\n metadata: ContentMetadata;\n \n /** Current lifecycle state */\n state: ReferenceLifecycleState;\n \n /** When this reference expires (if applicable) */\n expiresAt?: Date;\n}\n\n/**\n * Content storage for managing pruned conversation messages and large content references\n * Provides searchable storage with time-based querying and automatic cleanup.\n * \n * Extended to support reference-based storage for large content to optimize context window usage.\n */\nexport class ContentStorage implements ContentReferenceStore {\n private messages: StoredMessage[] = [];\n private maxStorage: number;\n private idCounter: number = 0;\n\n private contentStore: Map<ReferenceId, StoredContent> = new Map();\n private referenceConfig: ContentReferenceConfig;\n private cleanupTimer?: NodeJS.Timeout;\n private referenceStats: Omit<ContentReferenceStats, 'performanceMetrics'> & {\n performanceMetrics: ContentReferenceStats['performanceMetrics'] & {\n creationTimes: number[];\n resolutionTimes: number[];\n cleanupTimes: number[];\n };\n };\n\n public static readonly DEFAULT_MAX_STORAGE = 1000;\n\n constructor(\n maxStorage: number = ContentStorage.DEFAULT_MAX_STORAGE,\n referenceConfig?: Partial<ContentReferenceConfig>\n ) {\n this.maxStorage = maxStorage;\n \n this.referenceConfig = { ...DEFAULT_CONTENT_REFERENCE_CONFIG, ...referenceConfig };\n this.referenceStats = {\n activeReferences: 0,\n totalStorageBytes: 0,\n recentlyCleanedUp: 0,\n totalResolutions: 0,\n failedResolutions: 0,\n averageContentSize: 0,\n storageUtilization: 0,\n performanceMetrics: {\n averageCreationTimeMs: 0,\n averageResolutionTimeMs: 0,\n averageCleanupTimeMs: 0,\n creationTimes: [],\n resolutionTimes: [],\n cleanupTimes: []\n }\n };\n \n if (this.referenceConfig.enableAutoCleanup) {\n this.startReferenceCleanupTimer();\n }\n }\n\n /**\n * Store messages in the content storage\n * Automatically drops oldest messages if storage limit is exceeded\n * @param messages - Messages to store\n * @returns Result indicating how many messages were stored and dropped\n */\n storeMessages(messages: BaseMessage[]): StoreResult {\n if (messages.length === 0) {\n return { stored: 0, dropped: 0 };\n }\n\n const now = new Date();\n let dropped = 0;\n\n const storedMessages: StoredMessage[] = messages.map(message => ({\n message,\n storedAt: now,\n id: this.generateId()\n }));\n\n this.messages.push(...storedMessages);\n\n while (this.messages.length > this.maxStorage) {\n this.messages.shift();\n dropped++;\n }\n\n return {\n stored: storedMessages.length,\n dropped\n };\n }\n\n /**\n * Get the most recent messages from storage\n * @param count - Number of recent messages to retrieve\n * @returns Array of recent messages in chronological order\n */\n getRecentMessages(count: number): BaseMessage[] {\n if (count <= 0 || this.messages.length === 0) {\n return [];\n }\n\n const startIndex = Math.max(0, this.messages.length - count);\n return this.messages\n .slice(startIndex)\n .map(stored => stored.message);\n }\n\n /**\n * Search for messages containing specific text or patterns\n * @param query - Search term or regex pattern\n * @param options - Search configuration options\n * @returns Array of matching messages\n */\n searchMessages(query: string, options: SearchOptions = {}): BaseMessage[] {\n if (!query || this.messages.length === 0) {\n return [];\n }\n\n const {\n caseSensitive = false,\n limit,\n useRegex = false\n } = options;\n\n let matches: BaseMessage[] = [];\n\n if (useRegex) {\n try {\n const regex = new RegExp(query, caseSensitive ? 'g' : 'gi');\n matches = this.messages\n .filter(stored => regex.test(stored.message.content as string))\n .map(stored => stored.message);\n } catch (error) {\n return [];\n }\n } else {\n const searchTerm = caseSensitive ? query : query.toLowerCase();\n matches = this.messages\n .filter(stored => {\n const content = stored.message.content as string;\n const searchContent = caseSensitive ? content : content.toLowerCase();\n return searchContent.includes(searchTerm);\n })\n .map(stored => stored.message);\n }\n\n return limit ? matches.slice(0, limit) : matches;\n }\n\n /**\n * Get messages from a specific time range\n * @param startTime - Start of time range (inclusive)\n * @param endTime - End of time range (inclusive)\n * @returns Array of messages within the time range\n */\n getMessagesFromTimeRange(startTime: Date, endTime: Date): BaseMessage[] {\n if (startTime > endTime || this.messages.length === 0) {\n return [];\n }\n\n return this.messages\n .filter(stored => \n stored.storedAt >= startTime && stored.storedAt <= endTime\n )\n .map(stored => stored.message);\n }\n\n /**\n * Get storage statistics and usage information\n * @returns Current storage statistics\n */\n getStorageStats(): StorageStats {\n const totalMessages = this.messages.length;\n const usagePercentage = totalMessages > 0 \n ? Math.round((totalMessages / this.maxStorage) * 100)\n : 0;\n\n let oldestMessageTime: Date | undefined;\n let newestMessageTime: Date | undefined;\n\n if (totalMessages > 0) {\n oldestMessageTime = this.messages[0].storedAt;\n newestMessageTime = this.messages[totalMessages - 1].storedAt;\n }\n\n return {\n totalMessages,\n maxStorageLimit: this.maxStorage,\n usagePercentage,\n oldestMessageTime,\n newestMessageTime\n };\n }\n\n /**\n * Clear all stored messages\n */\n clear(): void {\n this.messages = [];\n this.idCounter = 0;\n }\n\n /**\n * Get total number of stored messages\n * @returns Number of messages currently in storage\n */\n getTotalStoredMessages(): number {\n return this.messages.length;\n }\n\n /**\n * Update the maximum storage limit\n * @param newLimit - New maximum storage limit\n */\n updateStorageLimit(newLimit: number): void {\n if (newLimit <= 0) {\n throw new Error('Storage limit must be greater than 0');\n }\n\n this.maxStorage = newLimit;\n\n while (this.messages.length > this.maxStorage) {\n this.messages.shift();\n }\n }\n\n /**\n * Get messages by message type\n * @param messageType - Type of messages to retrieve ('human', 'ai', 'system', etc.)\n * @param limit - Maximum number of messages to return\n * @returns Array of messages of the specified type\n */\n getMessagesByType(messageType: string, limit?: number): BaseMessage[] {\n const filtered = this.messages\n .filter(stored => stored.message._getType() === messageType)\n .map(stored => stored.message);\n\n return limit ? filtered.slice(0, limit) : filtered;\n }\n\n /**\n * Get the current storage configuration\n * @returns Storage configuration object\n */\n getConfig() {\n return {\n maxStorage: this.maxStorage,\n currentUsage: this.messages.length,\n utilizationPercentage: (this.messages.length / this.maxStorage) * 100\n };\n }\n\n /**\n * Generate a unique ID for stored messages\n * @returns Unique string identifier\n */\n private generateId(): string {\n return `msg_${++this.idCounter}_${Date.now()}`;\n }\n\n /**\n * Get messages stored within the last N minutes\n * @param minutes - Number of minutes to look back\n * @returns Array of messages from the last N minutes\n */\n getRecentMessagesByTime(minutes: number): BaseMessage[] {\n if (minutes <= 0 || this.messages.length === 0) {\n return [];\n }\n\n const cutoffTime = new Date(Date.now() - (minutes * 60 * 1000));\n \n return this.messages\n .filter(stored => stored.storedAt >= cutoffTime)\n .map(stored => stored.message);\n }\n\n /**\n * Export messages to a JSON-serializable format\n * @returns Serializable representation of stored messages\n */\n exportMessages() {\n return this.messages.map(stored => ({\n content: stored.message.content,\n type: stored.message._getType(),\n storedAt: stored.storedAt.toISOString(),\n id: stored.id\n }));\n }\n\n\n /**\n * Determine if content should be stored as a reference based on size\n */\n shouldUseReference(content: Buffer | string): boolean {\n const size = Buffer.isBuffer(content) ? content.length : Buffer.byteLength(content, 'utf8');\n return size > this.referenceConfig.sizeThresholdBytes;\n }\n\n /**\n * Store content and return a reference if it exceeds the size threshold\n * Otherwise returns null to indicate direct content should be used\n */\n async storeContentIfLarge(\n content: Buffer | string,\n metadata: {\n contentType?: ContentType;\n mimeType?: string;\n source: ContentSource;\n mcpToolName?: string;\n fileName?: string;\n tags?: string[];\n customMetadata?: Record<string, unknown>;\n }\n ): Promise<ContentReference | null> {\n const buffer = Buffer.isBuffer(content) ? content : Buffer.from(content, 'utf8');\n \n if (!this.shouldUseReference(buffer)) {\n return null;\n }\n \n const storeMetadata: Omit<ContentMetadata, 'createdAt' | 'lastAccessedAt' | 'accessCount'> = {\n contentType: metadata.contentType || this.detectContentType(buffer, metadata.mimeType),\n sizeBytes: buffer.length,\n source: metadata.source,\n tags: []\n };\n \n if (metadata.mimeType !== undefined) {\n storeMetadata.mimeType = metadata.mimeType;\n }\n if (metadata.mcpToolName !== undefined) {\n storeMetadata.mcpToolName = metadata.mcpToolName;\n }\n if (metadata.fileName !== undefined) {\n storeMetadata.fileName = metadata.fileName;\n }\n if (metadata.tags !== undefined) {\n storeMetadata.tags = metadata.tags;\n }\n if (metadata.customMetadata !== undefined) {\n storeMetadata.customMetadata = metadata.customMetadata;\n }\n \n return await this.storeContent(buffer, storeMetadata);\n }\n\n /**\n * Store content and return a reference (implements ContentReferenceStore)\n */\n async storeContent(\n content: Buffer,\n metadata: Omit<ContentMetadata, 'createdAt' | 'lastAccessedAt' | 'accessCount'>\n ): Promise<ContentReference> {\n const startTime = Date.now();\n \n try {\n const now = new Date();\n const referenceId = ReferenceIdGenerator.generateId(content);\n \n const fullMetadata: ContentMetadata = {\n ...metadata,\n createdAt: now,\n lastAccessedAt: now,\n accessCount: 0\n };\n \n const storedContent: StoredContent = {\n content,\n metadata: fullMetadata,\n state: 'active'\n };\n \n const expirationTime = this.calculateExpirationTime(metadata.source);\n if (expirationTime !== undefined) {\n storedContent.expiresAt = expirationTime;\n }\n \n this.contentStore.set(referenceId, storedContent);\n \n this.updateStatsAfterStore(content.length);\n \n await this.enforceReferenceStorageLimits();\n \n const preview = this.createContentPreview(content, fullMetadata.contentType);\n \n const referenceMetadata: Pick<ContentMetadata, 'contentType' | 'sizeBytes' | 'source' | 'fileName' | 'mimeType'> = {\n contentType: fullMetadata.contentType,\n sizeBytes: fullMetadata.sizeBytes,\n source: fullMetadata.source\n };\n \n if (fullMetadata.fileName !== undefined) {\n referenceMetadata.fileName = fullMetadata.fileName;\n }\n if (fullMetadata.mimeType !== undefined) {\n referenceMetadata.mimeType = fullMetadata.mimeType;\n }\n \n const reference: ContentReference = {\n referenceId,\n state: 'active',\n preview,\n metadata: referenceMetadata,\n createdAt: now,\n format: 'ref://{id}' as const\n };\n \n const duration = Date.now() - startTime;\n this.recordPerformanceMetric('creation', duration);\n \n return reference;\n } catch (error) {\n const duration = Date.now() - startTime;\n this.recordPerformanceMetric('creation', duration);\n \n throw new ContentReferenceError(\n `Failed to store content: ${error instanceof Error ? error.message : 'Unknown error'}`,\n 'system_error',\n undefined,\n ['Try again', 'Check storage limits', 'Contact administrator']\n );\n }\n }\n\n /**\n * Resolve a reference to its content (implements ContentReferenceStore)\n */\n async resolveReference(referenceId: ReferenceId): Promise<ReferenceResolutionResult> {\n const startTime = Date.now();\n \n try {\n if (!ReferenceIdGenerator.isValidReferenceId(referenceId)) {\n this.referenceStats.failedResolutions++;\n return {\n success: false,\n error: 'Invalid reference ID format',\n errorType: 'not_found',\n suggestedActions: ['Check the reference ID format', 'Ensure the reference ID is complete']\n };\n }\n \n const storedContent = this.contentStore.get(referenceId);\n \n if (!storedContent) {\n this.referenceStats.failedResolutions++;\n return {\n success: false,\n error: 'Reference not found',\n errorType: 'not_found',\n suggestedActions: ['Verify the reference ID', 'Check if the content has expired', 'Request fresh content']\n };\n }\n \n if (storedContent.expiresAt && storedContent.expiresAt < new Date()) {\n storedContent.state = 'expired';\n this.referenceStats.failedResolutions++;\n return {\n success: false,\n error: 'Reference has expired',\n errorType: 'expired',\n suggestedActions: ['Request fresh content', 'Use alternative content source']\n };\n }\n \n if (storedContent.state !== 'active') {\n this.referenceStats.failedResolutions++;\n return {\n success: false,\n error: `Reference is ${storedContent.state}`,\n errorType: storedContent.state === 'expired' ? 'expired' : 'corrupted',\n suggestedActions: ['Request fresh content', 'Check reference validity']\n };\n }\n \n storedContent.metadata.lastAccessedAt = new Date();\n storedContent.metadata.accessCount++;\n \n this.referenceStats.totalResolutions++;\n \n const duration = Date.now() - startTime;\n this.recordPerformanceMetric('resolution', duration);\n \n return {\n success: true,\n content: storedContent.content,\n metadata: storedContent.metadata\n };\n } catch (error) {\n const duration = Date.now() - startTime;\n this.recordPerformanceMetric('resolution', duration);\n \n this.referenceStats.failedResolutions++;\n \n return {\n success: false,\n error: `System error resolving reference: ${error instanceof Error ? error.message : 'Unknown error'}`,\n errorType: 'system_error',\n suggestedActions: ['Try again', 'Contact administrator']\n };\n }\n }\n\n /**\n * Check if a reference exists and is valid\n */\n async hasReference(referenceId: ReferenceId): Promise<boolean> {\n if (!ReferenceIdGenerator.isValidReferenceId(referenceId)) {\n return false;\n }\n \n const storedContent = this.contentStore.get(referenceId);\n if (!storedContent) {\n return false;\n }\n \n if (storedContent.expiresAt && storedContent.expiresAt < new Date()) {\n storedContent.state = 'expired';\n return false;\n }\n \n return storedContent.state === 'active';\n }\n\n /**\n * Mark a reference for cleanup\n */\n async cleanupReference(referenceId: ReferenceId): Promise<boolean> {\n const storedContent = this.contentStore.get(referenceId);\n if (!storedContent) {\n return false;\n }\n \n this.referenceStats.totalStorageBytes -= storedContent.content.length;\n this.referenceStats.activeReferences--;\n this.referenceStats.recentlyCleanedUp++;\n \n this.contentStore.delete(referenceId);\n \n return true;\n }\n\n /**\n * Get current reference storage statistics (implements ContentReferenceStore)\n */\n async getStats(): Promise<ContentReferenceStats> {\n this.updateReferenceStorageStats();\n \n return {\n ...this.referenceStats,\n performanceMetrics: {\n averageCreationTimeMs: this.calculateAverage(this.referenceStats.performanceMetrics.creationTimes),\n averageResolutionTimeMs: this.calculateAverage(this.referenceStats.performanceMetrics.resolutionTimes),\n averageCleanupTimeMs: this.calculateAverage(this.referenceStats.performanceMetrics.cleanupTimes)\n }\n };\n }\n\n /**\n * Update reference configuration\n */\n async updateConfig(config: Partial<ContentReferenceConfig>): Promise<void> {\n this.referenceConfig = { ...this.referenceConfig, ...config };\n \n if (this.cleanupTimer) {\n clearInterval(this.cleanupTimer);\n delete this.cleanupTimer;\n }\n \n if (this.referenceConfig.enableAutoCleanup) {\n this.startReferenceCleanupTimer();\n }\n }\n\n /**\n * Perform cleanup based on current policies (implements ContentReferenceStore)\n */\n async performCleanup(): Promise<{ cleanedUp: number; errors: string[] }> {\n const startTime = Date.now();\n const errors: string[] = [];\n let cleanedUp = 0;\n \n try {\n const now = new Date();\n const toCleanup: ReferenceId[] = [];\n \n for (const [referenceId, storedContent] of this.contentStore.entries()) {\n let shouldCleanup = false;\n \n if (storedContent.expiresAt && storedContent.expiresAt < now) {\n shouldCleanup = true;\n storedContent.state = 'expired';\n }\n \n const ageMs = now.getTime() - storedContent.metadata.createdAt.getTime();\n const policy = this.getCleanupPolicy(storedContent.metadata.source);\n \n if (ageMs > policy.maxAgeMs) {\n shouldCleanup = true;\n }\n \n if (storedContent.state === 'cleanup_pending') {\n shouldCleanup = true;\n }\n \n if (shouldCleanup) {\n toCleanup.push(referenceId);\n }\n }\n \n toCleanup.sort((a, b) => {\n const aContent = this.contentStore.get(a)!;\n const bContent = this.contentStore.get(b)!;\n const aPriority = this.getCleanupPolicy(aContent.metadata.source).priority;\n const bPriority = this.getCleanupPolicy(bContent.metadata.source).priority;\n return bPriority - aPriority;\n });\n \n for (const referenceId of toCleanup) {\n try {\n const success = await this.cleanupReference(referenceId);\n if (success) {\n cleanedUp++;\n }\n } catch (error) {\n errors.push(`Failed to cleanup ${referenceId}: ${error instanceof Error ? error.message : 'Unknown error'}`);\n }\n }\n \n if (this.contentStore.size > this.referenceConfig.maxReferences) {\n const sortedByAge = Array.from(this.contentStore.entries())\n .sort(([, a], [, b]) => a.metadata.lastAccessedAt.getTime() - b.metadata.lastAccessedAt.getTime());\n \n const excessCount = this.contentStore.size - this.referenceConfig.maxReferences;\n for (let i = 0; i < excessCount && i < sortedByAge.length; i++) {\n const [referenceId] = sortedByAge[i];\n try {\n const success = await this.cleanupReference(referenceId);\n if (success) {\n cleanedUp++;\n }\n } catch (error) {\n errors.push(`Failed to cleanup excess reference ${referenceId}: ${error instanceof Error ? error.message : 'Unknown error'}`);\n }\n }\n }\n \n const duration = Date.now() - startTime;\n this.recordPerformanceMetric('cleanup', duration);\n \n return { cleanedUp, errors };\n } catch (error) {\n const duration = Date.now() - startTime;\n this.recordPerformanceMetric('cleanup', duration);\n \n const errorMessage = `Cleanup process failed: ${error instanceof Error ? error.message : 'Unknown error'}`;\n errors.push(errorMessage);\n \n return { cleanedUp, errors };\n }\n }\n\n /**\n * Get reference configuration for debugging\n */\n getReferenceConfig(): ContentReferenceConfig {\n return { ...this.referenceConfig };\n }\n\n\n private async enforceReferenceStorageLimits(): Promise<void> {\n if (this.contentStore.size >= this.referenceConfig.maxReferences) {\n await this.performCleanup();\n }\n \n if (this.referenceStats.totalStorageBytes >= this.referenceConfig.maxTotalStorageBytes) {\n await this.performCleanup();\n }\n }\n\n private calculateExpirationTime(source: ContentSource): Date | undefined {\n const policy = this.getCleanupPolicy(source);\n return new Date(Date.now() + policy.maxAgeMs);\n }\n\n private getCleanupPolicy(source: ContentSource) {\n switch (source) {\n case 'mcp_tool':\n return this.referenceConfig.cleanupPolicies.recent;\n case 'user_upload':\n return this.referenceConfig.cleanupPolicies.userContent;\n case 'agent_generated':\n return this.referenceConfig.cleanupPolicies.agentGenerated;\n default:\n return this.referenceConfig.cleanupPolicies.default;\n }\n }\n\n private detectContentType(content: Buffer, mimeType?: string): ContentType {\n if (mimeType) {\n if (mimeType === 'text/html') return 'html';\n if (mimeType === 'text/markdown') return 'markdown';\n if (mimeType === 'application/json') return 'json';\n if (mimeType.startsWith('text/')) return 'text';\n return 'binary';\n }\n \n const contentStr = content.toString('utf8', 0, Math.min(content.length, 1000));\n if (contentStr.startsWith('{') || contentStr.startsWith('[')) return 'json';\n if (contentStr.includes('<html>') || contentStr.includes('<!DOCTYPE')) return 'html';\n if (contentStr.includes('#') && contentStr.includes('\\n')) return 'markdown';\n \n return 'text';\n }\n\n private createContentPreview(content: Buffer, contentType: ContentType): string {\n const maxLength = 200;\n let preview = content.toString('utf8', 0, Math.min(content.length, maxLength * 2));\n \n if (contentType === 'html') {\n preview = preview\n .replace(/<[^>]*>/g, '')\n .replace(/\\s+/g, ' ')\n .trim();\n } else if (contentType === 'json') {\n try {\n const parsed = JSON.parse(preview);\n preview = JSON.stringify(parsed, null, 0);\n } catch {\n }\n }\n \n preview = preview.trim();\n if (preview.length > maxLength) {\n preview = preview.substring(0, maxLength) + '...';\n }\n \n return preview || '[Binary content]';\n }\n\n private updateStatsAfterStore(sizeBytes: number): void {\n this.referenceStats.activeReferences++;\n this.referenceStats.totalStorageBytes += sizeBytes;\n this.updateReferenceStorageStats();\n }\n\n private updateReferenceStorageStats(): void {\n if (this.referenceStats.activeReferences > 0) {\n this.referenceStats.averageContentSize = this.referenceStats.totalStorageBytes / this.referenceStats.activeReferences;\n }\n \n this.referenceStats.storageUtilization = (this.referenceStats.totalStorageBytes / this.referenceConfig.maxTotalStorageBytes) * 100;\n \n let mostAccessedId: ReferenceId | undefined;\n let maxAccess = 0;\n \n for (const [referenceId, storedContent] of this.contentStore.entries()) {\n if (storedContent.metadata.accessCount > maxAccess) {\n maxAccess = storedContent.metadata.accessCount;\n mostAccessedId = referenceId;\n }\n }\n \n if (mostAccessedId !== undefined) {\n this.referenceStats.mostAccessedReferenceId = mostAccessedId;\n } else {\n delete this.referenceStats.mostAccessedReferenceId;\n }\n }\n\n private recordPerformanceMetric(type: 'creation' | 'resolution' | 'cleanup', timeMs: number): void {\n const metrics = this.referenceStats.performanceMetrics;\n const maxRecords = 100;\n \n switch (type) {\n case 'creation':\n metrics.creationTimes.push(timeMs);\n if (metrics.creationTimes.length > maxRecords) {\n metrics.creationTimes.shift();\n }\n break;\n case 'resolution':\n metrics.resolutionTimes.push(timeMs);\n if (metrics.resolutionTimes.length > maxRecords) {\n metrics.resolutionTimes.shift();\n }\n break;\n case 'cleanup':\n metrics.cleanupTimes.push(timeMs);\n if (metrics.cleanupTimes.length > maxRecords) {\n metrics.cleanupTimes.shift();\n }\n break;\n }\n }\n\n private calculateAverage(times: number[]): number {\n if (times.length === 0) return 0;\n return times.reduce((sum, time) => sum + time, 0) / times.length;\n }\n\n private startReferenceCleanupTimer(): void {\n this.cleanupTimer = setInterval(async () => {\n try {\n await this.performCleanup();\n } catch (error) {\n }\n }, this.referenceConfig.cleanupIntervalMs);\n }\n\n /**\n * Clean up resources (enhanced to include reference cleanup)\n */\n async dispose(): Promise<void> {\n if (this.cleanupTimer) {\n clearInterval(this.cleanupTimer);\n delete this.cleanupTimer;\n }\n \n this.contentStore.clear();\n \n this.clear();\n }\n}","import type { BaseMessage } from '@langchain/core/messages';\nimport { MemoryWindow } from './MemoryWindow';\nimport { ContentStorage } from './ContentStorage';\nimport { TokenCounter } from './TokenCounter';\n\n/**\n * Entity association for storing blockchain entity contexts\n */\nexport interface EntityAssociation {\n /** The blockchain entity ID (e.g., tokenId, accountId, topicId) */\n entityId: string;\n /** User-provided or derived friendly name */\n entityName: string;\n /** Type of entity (token, account, topic, schedule, etc.) */\n entityType: string;\n /** When the entity was created/associated */\n createdAt: Date;\n /** Transaction ID that created this entity */\n transactionId?: string;\n}\n\n/**\n * Options for resolving entity references\n */\nexport interface EntityResolutionOptions {\n /** Filter by specific entity type */\n entityType?: string;\n /** Maximum number of results to return */\n limit?: number;\n /** Whether to use fuzzy matching for natural language queries */\n fuzzyMatch?: boolean;\n}\n\n/**\n * Configuration for SmartMemoryManager\n */\nexport interface SmartMemoryConfig {\n /** Maximum tokens for active memory window */\n maxTokens?: number;\n /** Reserve tokens for response generation */\n reserveTokens?: number;\n /** Model name for token counting */\n modelName?: string;\n /** Maximum messages to store in content storage */\n storageLimit?: number;\n}\n\n/**\n * Search options for history search\n */\nexport interface SearchOptions {\n /** Whether to perform case-sensitive search */\n caseSensitive?: boolean;\n /** Maximum number of results to return */\n limit?: number;\n /** Whether to use regex pattern matching */\n useRegex?: boolean;\n}\n\n/**\n * Memory statistics for active memory window\n */\nexport interface MemoryStats {\n /** Total active messages in memory window */\n totalActiveMessages: number;\n /** Current token count including system prompt */\n currentTokenCount: number;\n /** Maximum token capacity */\n maxTokens: number;\n /** Remaining token capacity */\n remainingCapacity: number;\n /** System prompt token count */\n systemPromptTokens: number;\n /** Memory usage percentage */\n usagePercentage: number;\n}\n\nconst IS_ENTITY_ASSOCIATION_FLAG = '\"isEntityAssociation\":true';\n\n\n/**\n * TODO: investigate using chroma / rag for long term memory\n * Smart memory manager that combines active memory window with long-term storage\n * Provides context-aware memory management with automatic pruning and searchable history\n */\nexport class SmartMemoryManager {\n private memoryWindow: MemoryWindow;\n private _contentStorage: ContentStorage;\n private tokenCounter: TokenCounter;\n private config: Required<SmartMemoryConfig>;\n\n private static readonly DEFAULT_CONFIG: Required<SmartMemoryConfig> = {\n maxTokens: 8000,\n reserveTokens: 1000,\n modelName: 'gpt-4o',\n storageLimit: 1000,\n };\n\n constructor(config: SmartMemoryConfig = {}) {\n this.config = { ...SmartMemoryManager.DEFAULT_CONFIG, ...config };\n\n this.tokenCounter = new TokenCounter(this.config.modelName);\n this._contentStorage = new ContentStorage(this.config.storageLimit);\n this.memoryWindow = new MemoryWindow(\n this.config.maxTokens,\n this.config.reserveTokens,\n this.tokenCounter\n );\n }\n\n /**\n * Get the content storage instance for file/content reference operations\n * @returns ContentStorage instance\n */\n get contentStorage(): ContentStorage {\n return this._contentStorage;\n }\n\n /**\n * Add a message to the active memory window\n * Automatically handles pruning and storage of displaced messages\n * @param message - Message to add\n */\n addMessage(message: BaseMessage): void {\n const result = this.memoryWindow.addMessage(message);\n\n if (result.prunedMessages.length > 0) {\n this._contentStorage.storeMessages(result.prunedMessages);\n }\n }\n\n /**\n * Get all active messages from the memory window\n * @returns Array of active messages in chronological order\n */\n getMessages(): BaseMessage[] {\n return this.memoryWindow.getMessages();\n }\n\n /**\n * Clear active memory window\n * @param clearStorage - Whether to also clear the content storage (default: false)\n */\n clear(clearStorage: boolean = false): void {\n this.memoryWindow.clear();\n\n if (clearStorage) {\n this._contentStorage.clear();\n }\n }\n\n /**\n * Set the system prompt for the memory window\n * @param systemPrompt - System prompt text\n */\n setSystemPrompt(systemPrompt: string): void {\n this.memoryWindow.setSystemPrompt(systemPrompt);\n }\n\n /**\n * Get the current system prompt\n * @returns Current system prompt text\n */\n getSystemPrompt(): string {\n return this.memoryWindow.getSystemPrompt();\n }\n\n /**\n * Search through stored message history\n * @param query - Search term or pattern\n * @param options - Search configuration\n * @returns Array of matching messages from history\n */\n searchHistory(query: string, options: SearchOptions = {}): BaseMessage[] {\n return this._contentStorage.searchMessages(query, options);\n }\n\n /**\n * Get recent messages from storage history\n * @param count - Number of recent messages to retrieve\n * @returns Array of recent messages from storage\n */\n getRecentHistory(count: number): BaseMessage[] {\n return this._contentStorage.getRecentMessages(count);\n }\n\n /**\n * Check if a message can be added without exceeding limits\n * @param message - Message to test\n * @returns True if message can be added\n */\n canAddMessage(message: BaseMessage): boolean {\n return this.memoryWindow.canAddMessage(message);\n }\n\n /**\n * Get statistics about the active memory window\n * @returns Memory usage statistics\n */\n getMemoryStats(): MemoryStats {\n const windowStats = this.memoryWindow.getStats();\n\n return {\n totalActiveMessages: windowStats.totalMessages,\n currentTokenCount: windowStats.currentTokens,\n maxTokens: windowStats.maxTokens,\n remainingCapacity: windowStats.remainingCapacity,\n systemPromptTokens: windowStats.systemPromptTokens,\n usagePercentage: windowStats.usagePercentage,\n };\n }\n\n /**\n * Get statistics about the content storage\n * @returns Storage usage statistics\n */\n getStorageStats(): ReturnType<ContentStorage['getStorageStats']> {\n return this._contentStorage.getStorageStats();\n }\n\n /**\n * Get combined statistics for both active memory and storage\n * @returns Combined memory and storage statistics\n */\n getOverallStats(): {\n activeMemory: MemoryStats;\n storage: ReturnType<ContentStorage['getStorageStats']>;\n totalMessagesManaged: number;\n activeMemoryUtilization: number;\n storageUtilization: number;\n } {\n const memoryStats = this.getMemoryStats();\n const storageStats = this.getStorageStats();\n\n return {\n activeMemory: memoryStats,\n storage: storageStats,\n totalMessagesManaged:\n memoryStats.totalActiveMessages + storageStats.totalMessages,\n activeMemoryUtilization: memoryStats.usagePercentage,\n storageUtilization: storageStats.usagePercentage,\n };\n }\n\n /**\n * Update the configuration and apply changes\n * @param newConfig - New configuration options\n */\n updateConfig(newConfig: Partial<SmartMemoryConfig>): void {\n this.config = { ...this.config, ...newConfig };\n\n if (\n newConfig.maxTokens !== undefined ||\n newConfig.reserveTokens !== undefined\n ) {\n this.memoryWindow.updateLimits(\n this.config.maxTokens,\n this.config.reserveTokens\n );\n }\n\n if (newConfig.storageLimit !== undefined) {\n this._contentStorage.updateStorageLimit(this.config.storageLimit);\n }\n }\n\n /**\n * Get current configuration\n * @returns Current configuration settings\n */\n getConfig(): Required<SmartMemoryConfig> {\n return { ...this.config };\n }\n\n /**\n * Get messages from storage within a time range\n * @param startTime - Start of time range\n * @param endTime - End of time range\n * @returns Messages within the specified time range\n */\n getHistoryFromTimeRange(startTime: Date, endTime: Date): BaseMessage[] {\n return this._contentStorage.getMessagesFromTimeRange(startTime, endTime);\n }\n\n /**\n * Get messages from storage by message type\n * @param messageType - Type of messages to retrieve ('human', 'ai', 'system', etc.)\n * @param limit - Maximum number of messages to return\n * @returns Messages of the specified type\n */\n getHistoryByType(messageType: string, limit?: number): BaseMessage[] {\n return this._contentStorage.getMessagesByType(messageType, limit);\n }\n\n /**\n * Get recent messages from storage within the last N minutes\n * @param minutes - Number of minutes to look back\n * @returns Messages from the last N minutes\n */\n getRecentHistoryByTime(minutes: number): BaseMessage[] {\n return this._contentStorage.getRecentMessagesByTime(minutes);\n }\n\n /**\n * Export the current state for persistence or analysis\n * @returns Serializable representation of memory state\n */\n exportState(): {\n config: Required<SmartMemoryConfig>;\n activeMessages: Array<{ content: unknown; type: string }>;\n systemPrompt: string;\n memoryStats: MemoryStats;\n storageStats: ReturnType<ContentStorage['getStorageStats']>;\n storedMessages: ReturnType<ContentStorage['exportMessages']>;\n } {\n return {\n config: this.config,\n activeMessages: this.memoryWindow.getMessages().map((msg) => ({\n content: msg.content,\n type: msg._getType(),\n })),\n systemPrompt: this.memoryWindow.getSystemPrompt(),\n memoryStats: this.getMemoryStats(),\n storageStats: this.getStorageStats(),\n storedMessages: this._contentStorage.exportMessages(),\n };\n }\n\n /**\n * Get a summary of conversation context for external use\n * Useful for providing context to other systems or for logging\n * @param includeStoredContext - Whether to include recent stored messages\n * @returns Context summary object\n */\n getContextSummary(includeStoredContext: boolean = false): {\n activeMessageCount: number;\n systemPrompt: string;\n recentMessages: BaseMessage[];\n memoryUtilization: number;\n hasStoredHistory: boolean;\n recentStoredMessages?: BaseMessage[];\n storageStats?: ReturnType<ContentStorage['getStorageStats']>;\n } {\n const activeMessages = this.getMessages();\n const summary = {\n activeMessageCount: activeMessages.length,\n systemPrompt: this.getSystemPrompt(),\n recentMessages: activeMessages.slice(-5),\n memoryUtilization: this.getMemoryStats().usagePercentage,\n hasStoredHistory: this.getStorageStats().totalMessages > 0,\n };\n\n if (includeStoredContext) {\n return {\n ...summary,\n recentStoredMessages: this.getRecentHistory(10),\n storageStats: this.getStorageStats(),\n };\n }\n\n return summary;\n }\n\n /**\n * Perform maintenance operations\n * Optimizes storage and cleans up resources\n */\n performMaintenance(): void {}\n\n /**\n * Store an entity association for later resolution\n * @param entityId - The blockchain entity ID\n * @param entityName - User-provided or derived friendly name\n * @param entityType - Type of entity (token, account, topic, etc.)\n * @param transactionId - Optional transaction ID that created this entity\n */\n storeEntityAssociation(\n entityId: string,\n entityName: string,\n entityType: string,\n transactionId?: string\n ): void {\n try {\n if (\n !entityId ||\n typeof entityId !== 'string' ||\n entityId.trim().length === 0\n ) {\n return;\n }\n\n if (\n !entityName ||\n typeof entityName !== 'string' ||\n entityName.trim().length === 0\n ) {\n return;\n }\n\n if (\n !entityType ||\n typeof entityType !== 'string' ||\n entityType.trim().length === 0\n ) {\n return;\n }\n\n const sanitizedEntityId = entityId.trim();\n const sanitizedEntityName = entityName.trim().substring(0, 100);\n const sanitizedEntityType = entityType.trim().toLowerCase();\n\n const association: EntityAssociation & { isEntityAssociation: boolean } =\n {\n entityId: sanitizedEntityId,\n entityName: sanitizedEntityName,\n entityType: sanitizedEntityType,\n createdAt: new Date(),\n isEntityAssociation: true,\n ...(transactionId !== undefined &&\n transactionId !== null &&\n transactionId.trim() !== ''\n ? { transactionId: transactionId.trim() }\n : {}),\n };\n\n const content = JSON.stringify(association);\n type LangChainLikeMessage = {\n _getType: () => string;\n content: unknown;\n id: string;\n name?: string;\n additional_kwargs?: Record<string, unknown>;\n };\n\n const entityMessage: LangChainLikeMessage = {\n _getType: () => 'system',\n content: content,\n id: `entity_${sanitizedEntityId}_${Date.now()}`,\n name: 'entity_association',\n additional_kwargs: {\n entityId: sanitizedEntityId,\n entityName: sanitizedEntityName,\n entityType: sanitizedEntityType,\n isEntityAssociation: true,\n },\n };\n\n this._contentStorage.storeMessages([entityMessage as BaseMessage]);\n } catch (_error) {}\n }\n\n /**\n * Resolve entity references from natural language queries\n * @param query - Search query (entity name or natural language reference)\n * @param options - Resolution options for filtering and fuzzy matching\n * @returns Array of matching entity associations\n */\n resolveEntityReference(\n query: string,\n options: EntityResolutionOptions = {}\n ): EntityAssociation[] {\n try {\n if (!query || typeof query !== 'string') {\n return [];\n }\n\n const sanitizedQuery = query.trim();\n if (sanitizedQuery.length === 0) {\n return [];\n }\n\n if (sanitizedQuery.length > 200) {\n }\n\n const { entityType, limit = 10, fuzzyMatch = true } = options;\n\n const safeLimit = Math.max(1, Math.min(limit || 10, 100));\n\n const isEntityIdQuery = /^0\\.0\\.\\d+$/.test(sanitizedQuery);\n\n const searchResults = this._contentStorage.searchMessages(\n sanitizedQuery.substring(0, 200),\n {\n caseSensitive: false,\n limit: safeLimit * 2,\n }\n );\n\n const associations: EntityAssociation[] = [];\n\n for (const message of searchResults) {\n try {\n const content = message.content as string;\n if (\n content.includes(IS_ENTITY_ASSOCIATION_FLAG) ||\n content.includes('entityId')\n ) {\n const parsed = JSON.parse(content);\n if (parsed.entityId && parsed.entityName && parsed.entityType) {\n if (entityType && parsed.entityType !== entityType) {\n continue;\n }\n\n if (isEntityIdQuery) {\n if (parsed.entityId !== sanitizedQuery) {\n continue;\n }\n }\n\n associations.push(parsed as EntityAssociation);\n }\n }\n } catch {\n continue;\n }\n }\n\n if (fuzzyMatch && associations.length === 0 && !isEntityIdQuery) {\n const fuzzyQueries = [\n query.toLowerCase(),\n `token`,\n `account`,\n entityType || '',\n ].filter(Boolean);\n\n for (const fuzzyQuery of fuzzyQueries) {\n if (fuzzyQuery === query.toLowerCase()) continue;\n\n const fuzzyResults = this._contentStorage.searchMessages(fuzzyQuery, {\n caseSensitive: false,\n limit: limit,\n });\n\n for (const message of fuzzyResults) {\n try {\n const content = message.content as string;\n if (content.includes(IS_ENTITY_ASSOCIATION_FLAG)) {\n const parsed = JSON.parse(content);\n if (parsed.entityId && parsed.entityName && parsed.entityType) {\n if (entityType && parsed.entityType !== entityType) {\n continue;\n }\n associations.push(parsed as EntityAssociation);\n }\n }\n } catch {\n continue;\n }\n }\n }\n }\n\n const uniqueAssociations = associations\n .filter(\n (assoc, index, arr) =>\n arr.findIndex((a) => a.entityId === assoc.entityId) === index\n )\n .sort(\n (a, b) =>\n new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()\n );\n\n const results = uniqueAssociations.slice(0, safeLimit);\n\n return results;\n } catch (_error) {\n return [];\n }\n }\n\n /**\n * Get all entity associations, optionally filtered by type\n * @param entityType - Optional filter by entity type\n * @returns Array of entity associations\n */\n getEntityAssociations(entityType?: string): EntityAssociation[] {\n try {\n const sanitizedEntityType = entityType\n ? entityType.trim().toLowerCase()\n : undefined;\n\n if (\n entityType &&\n (!sanitizedEntityType || sanitizedEntityType.length === 0)\n ) {\n return [];\n }\n\n const SEARCH_ANY_ENTITY = 'entityId';\n const searchQuery = sanitizedEntityType || SEARCH_ANY_ENTITY;\n const searchResults = this._contentStorage.searchMessages(searchQuery, {\n caseSensitive: false,\n limit: 100,\n });\n\n const associations: EntityAssociation[] = [];\n\n for (const message of searchResults) {\n try {\n const content = message.content as string;\n if (content.includes(IS_ENTITY_ASSOCIATION_FLAG)) {\n const parsed = JSON.parse(content);\n\n if (parsed.entityId && parsed.entityName && parsed.entityType) {\n if (\n sanitizedEntityType &&\n parsed.entityType !== sanitizedEntityType\n ) {\n continue;\n }\n\n if (parsed.createdAt && typeof parsed.createdAt === 'string') {\n parsed.createdAt = new Date(parsed.createdAt);\n }\n\n associations.push(parsed as EntityAssociation);\n }\n }\n } catch (_parseError) {\n continue;\n }\n }\n\n const results = associations\n .filter(\n (assoc, index, arr) =>\n arr.findIndex((a) => a.entityId === assoc.entityId) === index\n )\n .sort((a, b): number => {\n const getTime = (d: Date | string): number =>\n d instanceof Date ? d.getTime() : new Date(d).getTime();\n const aTime = getTime(a.createdAt);\n const bTime = getTime(b.createdAt);\n return bTime - aTime;\n });\n\n return results;\n } catch (_error) {\n return [];\n }\n }\n\n /**\n * Clean up resources and dispose of components\n */\n dispose(): void {\n this.memoryWindow.dispose();\n this._contentStorage.dispose();\n this.tokenCounter.dispose();\n }\n}\n","import type { BaseChatModel } from '@langchain/core/language_models/chat_models';\nimport type { StructuredTool } from '@langchain/core/tools';\nimport { createOpenAIToolsAgent } from 'langchain/agents';\nimport { ContentAwareAgentExecutor } from './langchain/ContentAwareAgentExecutor';\nimport {\n ChatPromptTemplate,\n MessagesPlaceholder,\n} from '@langchain/core/prompts';\nimport { ChatOpenAI } from '@langchain/openai';\nimport {\n calculateTokenCostSync,\n getAllHederaCorePlugins,\n HederaAgentKit,\n TokenUsageCallbackHandler,\n} from 'hedera-agent-kit';\nimport type { TokenUsage, CostCalculation } from 'hedera-agent-kit';\nimport {\n BaseAgent,\n type ConversationContext,\n type ChatResponse,\n type OperationalMode,\n type UsageStats,\n} from './base-agent';\nimport { MCPClientManager } from './mcp/MCPClientManager';\nimport { convertMCPToolToLangChain } from './mcp/adapters/langchain';\nimport { SmartMemoryManager } from './memory/SmartMemoryManager';\nimport type { MCPConnectionStatus } from './mcp/types';\n\nexport class LangChainAgent extends BaseAgent {\n private executor: ContentAwareAgentExecutor | undefined;\n private systemMessage = '';\n private mcpManager?: MCPClientManager;\n private smartMemory: SmartMemoryManager | undefined;\n private mcpConnectionStatus: Map<string, MCPConnectionStatus> = new Map();\n\n async boot(): Promise<void> {\n if (this.initialized) {\n this.logger.warn('Agent already initialized');\n return;\n }\n\n try {\n this.agentKit = await this.createAgentKit();\n await this.agentKit.initialize();\n\n const modelName =\n this.config.ai?.modelName ||\n process.env.OPENAI_MODEL_NAME ||\n 'gpt-4o-mini';\n this.tokenTracker = new TokenUsageCallbackHandler(modelName);\n\n const allTools = this.agentKit.getAggregatedLangChainTools();\n this.tools = this.filterTools(allTools);\n\n if (this.config.mcp?.servers && this.config.mcp.servers.length > 0) {\n if (this.config.mcp.autoConnect !== false) {\n await this.initializeMCP();\n } else {\n this.logger.info(\n 'MCP servers configured but autoConnect=false, skipping synchronous connection'\n );\n this.mcpManager = new MCPClientManager(this.logger);\n }\n }\n\n this.smartMemory = new SmartMemoryManager({\n modelName,\n maxTokens: 90000,\n reserveTokens: 10000,\n storageLimit: 1000,\n });\n\n this.logger.info('SmartMemoryManager initialized:', {\n modelName,\n toolsCount: this.tools.length,\n maxTokens: 90000,\n reserveTokens: 10000,\n });\n\n this.systemMessage = this.buildSystemPrompt();\n\n this.smartMemory.setSystemPrompt(this.systemMessage);\n\n await this.createExecutor();\n\n this.initialized = true;\n this.logger.info('LangChain Hedera agent initialized');\n } catch (error) {\n this.logger.error('Failed to initialize agent:', error);\n throw error;\n }\n }\n\n async chat(\n message: string,\n context?: ConversationContext\n ): Promise<ChatResponse> {\n if (!this.initialized || !this.executor || !this.smartMemory) {\n throw new Error('Agent not initialized. Call boot() first.');\n }\n\n try {\n this.logger.info('LangChainAgent.chat called with:', {\n message,\n contextLength: context?.messages?.length || 0,\n });\n\n if (context?.messages && context.messages.length > 0) {\n this.smartMemory.clear();\n\n for (const msg of context.messages) {\n this.smartMemory.addMessage(msg);\n }\n }\n\n const { HumanMessage } = await import('@langchain/core/messages');\n this.smartMemory.addMessage(new HumanMessage(message));\n\n const memoryStats = this.smartMemory.getMemoryStats();\n this.logger.info('Memory stats before execution:', {\n totalMessages: memoryStats.totalActiveMessages,\n currentTokens: memoryStats.currentTokenCount,\n maxTokens: memoryStats.maxTokens,\n usagePercentage: memoryStats.usagePercentage,\n toolsCount: this.tools.length,\n });\n\n const result = await this.executor.invoke({\n input: message,\n chat_history: this.smartMemory.getMessages(),\n });\n\n this.logger.info('LangChainAgent executor result:', result);\n\n let response: ChatResponse = {\n output: result.output || '',\n message: result.output || '',\n notes: [],\n intermediateSteps: result.intermediateSteps,\n };\n\n if (result.intermediateSteps && Array.isArray(result.intermediateSteps)) {\n const toolCalls = result.intermediateSteps.map(\n (step: any, index: number) => ({\n id: `call_${index}`,\n name: step.action?.tool || 'unknown',\n args: step.action?.toolInput || {},\n output:\n typeof step.observation === 'string'\n ? step.observation\n : JSON.stringify(step.observation),\n })\n );\n\n if (toolCalls.length > 0) {\n response.tool_calls = toolCalls;\n }\n }\n\n const parsedSteps = result?.intermediateSteps?.[0]?.observation;\n if (\n parsedSteps &&\n typeof parsedSteps === 'string' &&\n this.isJSON(parsedSteps)\n ) {\n try {\n const parsed = JSON.parse(parsedSteps);\n response = { ...response, ...parsed };\n } catch (error) {\n this.logger.error('Error parsing intermediate steps:', error);\n }\n }\n\n if (!response.output || response.output.trim() === '') {\n response.output = 'Agent action complete.';\n }\n\n if (response.output) {\n const { AIMessage } = await import('@langchain/core/messages');\n this.smartMemory.addMessage(new AIMessage(response.output));\n }\n\n if (this.tokenTracker) {\n const tokenUsage = this.tokenTracker.getLatestTokenUsage();\n if (tokenUsage) {\n response.tokenUsage = tokenUsage;\n response.cost = calculateTokenCostSync(tokenUsage);\n }\n }\n\n const finalMemoryStats = this.smartMemory.getMemoryStats();\n response.metadata = {\n ...response.metadata,\n memoryStats: {\n activeMessages: finalMemoryStats.totalActiveMessages,\n tokenUsage: finalMemoryStats.currentTokenCount,\n maxTokens: finalMemoryStats.maxTokens,\n usagePercentage: finalMemoryStats.usagePercentage,\n },\n };\n\n this.logger.info('LangChainAgent.chat returning response:', response);\n return response;\n } catch (error) {\n this.logger.error('LangChainAgent.chat error:', error);\n return this.handleError(error);\n }\n }\n\n async shutdown(): Promise<void> {\n if (this.mcpManager) {\n await this.mcpManager.disconnectAll();\n }\n\n if (this.smartMemory) {\n this.smartMemory.dispose();\n this.smartMemory = undefined;\n }\n\n this.executor = undefined;\n this.agentKit = undefined;\n this.tools = [];\n this.initialized = false;\n this.logger.info('Agent cleaned up');\n }\n\n switchMode(mode: OperationalMode): void {\n if (this.config.execution) {\n this.config.execution.operationalMode = mode;\n } else {\n this.config.execution = { operationalMode: mode };\n }\n\n if (this.agentKit) {\n this.agentKit.operationalMode = mode;\n }\n\n this.systemMessage = this.buildSystemPrompt();\n this.logger.info(`Operational mode switched to: ${mode}`);\n }\n\n getUsageStats(): UsageStats {\n if (!this.tokenTracker) {\n return {\n promptTokens: 0,\n completionTokens: 0,\n totalTokens: 0,\n cost: { totalCost: 0 } as CostCalculation,\n };\n }\n\n const usage = this.tokenTracker.getTotalTokenUsage();\n const cost = calculateTokenCostSync(usage);\n return { ...usage, cost };\n }\n\n getUsageLog(): UsageStats[] {\n if (!this.tokenTracker) {\n return [];\n }\n\n return this.tokenTracker.getTokenUsageHistory().map((usage) => ({\n ...usage,\n cost: calculateTokenCostSync(usage),\n }));\n }\n\n clearUsageStats(): void {\n if (this.tokenTracker) {\n this.tokenTracker.reset();\n this.logger.info('Usage statistics cleared');\n }\n }\n\n getMCPConnectionStatus(): Map<string, MCPConnectionStatus> {\n return new Map(this.mcpConnectionStatus);\n }\n\n private async createAgentKit(): Promise<HederaAgentKit> {\n const corePlugins = getAllHederaCorePlugins();\n const extensionPlugins = this.config.extensions?.plugins || [];\n const plugins = [...corePlugins, ...extensionPlugins];\n\n const operationalMode =\n this.config.execution?.operationalMode || 'returnBytes';\n const modelName = this.config.ai?.modelName || 'gpt-4o';\n\n return new HederaAgentKit(\n this.config.signer,\n { plugins },\n operationalMode,\n this.config.execution?.userAccountId,\n this.config.execution?.scheduleUserTransactionsInBytesMode ?? false,\n undefined,\n modelName,\n this.config.extensions?.mirrorConfig,\n this.config.debug?.silent ?? false\n );\n }\n\n private async createExecutor(): Promise<void> {\n let llm: BaseChatModel;\n if (this.config.ai?.provider && this.config.ai.provider.getModel) {\n llm = this.config.ai.provider.getModel() as BaseChatModel;\n } else if (this.config.ai?.llm) {\n llm = this.config.ai.llm as BaseChatModel;\n } else {\n const apiKey = this.config.ai?.apiKey || process.env.OPENAI_API_KEY;\n if (!apiKey) {\n throw new Error('OpenAI API key required');\n }\n\n const modelName = this.config.ai?.modelName || 'gpt-4o-mini';\n const isGPT5Model =\n modelName.toLowerCase().includes('gpt-5') ||\n modelName.toLowerCase().includes('gpt5');\n\n llm = new ChatOpenAI({\n apiKey,\n modelName,\n callbacks: this.tokenTracker ? [this.tokenTracker] : [],\n ...(isGPT5Model ? { temperature: 1 } : {}),\n });\n }\n\n const prompt = ChatPromptTemplate.fromMessages([\n ['system', this.systemMessage],\n new MessagesPlaceholder('chat_history'),\n ['human', '{input}'],\n new MessagesPlaceholder('agent_scratchpad'),\n ]);\n\n const langchainTools = this.tools as unknown as StructuredTool[];\n\n const agent = await createOpenAIToolsAgent({\n llm,\n tools: langchainTools,\n prompt,\n });\n\n this.executor = new ContentAwareAgentExecutor({\n agent,\n tools: langchainTools,\n verbose: this.config.debug?.verbose ?? false,\n returnIntermediateSteps: true,\n });\n }\n\n private handleError(error: unknown): ChatResponse {\n const errorMessage =\n error instanceof Error ? error.message : 'Unknown error';\n this.logger.error('Chat error:', error);\n\n let tokenUsage: TokenUsage | undefined;\n let cost: CostCalculation | undefined;\n\n if (this.tokenTracker) {\n tokenUsage = this.tokenTracker.getLatestTokenUsage();\n if (tokenUsage) {\n cost = calculateTokenCostSync(tokenUsage);\n }\n }\n\n let userFriendlyMessage = errorMessage;\n let userFriendlyOutput = errorMessage;\n\n if (errorMessage.includes('429')) {\n if (errorMessage.includes('quota')) {\n userFriendlyMessage =\n 'API quota exceeded. Please check your OpenAI billing and usage limits.';\n userFriendlyOutput =\n \"I'm currently unable to respond because the API quota has been exceeded. Please check your OpenAI account billing and usage limits, then try again.\";\n } else {\n userFriendlyMessage =\n 'Too many requests. Please wait a moment and try again.';\n userFriendlyOutput =\n \"I'm receiving too many requests right now. Please wait a moment and try again.\";\n }\n } else if (\n errorMessage.includes('401') ||\n errorMessage.includes('unauthorized')\n ) {\n userFriendlyMessage =\n 'API authentication failed. Please check your API key configuration.';\n userFriendlyOutput =\n \"There's an issue with the API authentication. Please check your OpenAI API key configuration in settings.\";\n } else if (errorMessage.includes('timeout')) {\n userFriendlyMessage = 'Request timed out. Please try again.';\n userFriendlyOutput =\n 'The request took too long to process. Please try again.';\n } else if (\n errorMessage.includes('network') ||\n errorMessage.includes('fetch')\n ) {\n userFriendlyMessage =\n 'Network error. Please check your internet connection and try again.';\n userFriendlyOutput =\n 'There was a network error. Please check your internet connection and try again.';\n } else if (errorMessage.includes('400')) {\n userFriendlyMessage = errorMessage;\n userFriendlyOutput = errorMessage;\n }\n\n const errorResponse: ChatResponse = {\n output: userFriendlyOutput,\n message: userFriendlyMessage,\n error: errorMessage,\n notes: [],\n };\n\n if (tokenUsage) {\n errorResponse.tokenUsage = tokenUsage;\n }\n\n if (cost) {\n errorResponse.cost = cost;\n }\n\n return errorResponse;\n }\n\n private async initializeMCP(): Promise<void> {\n this.mcpManager = new MCPClientManager(this.logger);\n\n for (const serverConfig of this.config.mcp!.servers!) {\n if (serverConfig.autoConnect === false) {\n this.logger.info(\n `Skipping MCP server ${serverConfig.name} (autoConnect=false)`\n );\n continue;\n }\n\n const status = await this.mcpManager.connectServer(serverConfig);\n\n if (status.connected) {\n this.logger.info(\n `Connected to MCP server ${status.serverName} with ${status.tools.length} tools`\n );\n\n for (const mcpTool of status.tools) {\n const langchainTool = convertMCPToolToLangChain(\n mcpTool,\n this.mcpManager,\n serverConfig\n );\n this.tools.push(langchainTool);\n }\n } else {\n this.logger.error(\n `Failed to connect to MCP server ${status.serverName}: ${status.error}`\n );\n }\n }\n }\n\n /**\n * Connect to MCP servers asynchronously after agent boot with background timeout pattern\n */\n async connectMCPServers(): Promise<void> {\n if (!this.config.mcp?.servers || this.config.mcp.servers.length === 0) {\n return;\n }\n\n if (!this.mcpManager) {\n this.mcpManager = new MCPClientManager(this.logger);\n }\n\n this.logger.info(\n `Starting background MCP server connections for ${this.config.mcp.servers.length} servers...`\n );\n\n this.config.mcp.servers.forEach((serverConfig) => {\n this.connectServerInBackground(serverConfig);\n });\n\n this.logger.info('MCP server connections initiated in background');\n }\n\n /**\n * Connect to a single MCP server in background with timeout\n */\n private connectServerInBackground(serverConfig: any): void {\n const serverName = serverConfig.name;\n\n setTimeout(async () => {\n try {\n this.logger.info(`Background connecting to MCP server: ${serverName}`);\n\n const status = await this.mcpManager!.connectServer(serverConfig);\n this.mcpConnectionStatus.set(serverName, status);\n\n if (status.connected) {\n this.logger.info(\n `Successfully connected to MCP server ${status.serverName} with ${status.tools.length} tools`\n );\n\n for (const mcpTool of status.tools) {\n const langchainTool = convertMCPToolToLangChain(\n mcpTool,\n this.mcpManager!,\n serverConfig\n );\n this.tools.push(langchainTool);\n }\n\n if (this.initialized && this.executor) {\n this.logger.info(\n `Recreating executor with ${this.tools.length} total tools`\n );\n await this.createExecutor();\n }\n } else {\n this.logger.error(\n `Failed to connect to MCP server ${status.serverName}: ${status.error}`\n );\n }\n } catch (error) {\n this.logger.error(\n `Background connection failed for MCP server ${serverName}:`,\n error\n );\n\n this.mcpConnectionStatus.set(serverName, {\n connected: false,\n serverName,\n tools: [],\n error: error instanceof Error ? error.message : 'Connection failed',\n });\n }\n }, 1000);\n }\n\n /**\n * Check if a string is valid JSON\n */\n private isJSON(str: string): boolean {\n if (typeof str !== 'string') return false;\n\n const trimmed = str.trim();\n if (!trimmed) return false;\n\n if (\n !(trimmed.startsWith('{') && trimmed.endsWith('}')) &&\n !(trimmed.startsWith('[') && trimmed.endsWith(']'))\n ) {\n return false;\n }\n\n try {\n JSON.parse(trimmed);\n return true;\n } catch {\n return false;\n }\n }\n}\n","import { BaseAgent, type HederaAgentConfiguration } from './base-agent';\nimport { LangChainAgent } from './langchain-agent';\n\nexport function createAgent(\n config: HederaAgentConfiguration & {\n framework?: 'langchain' | 'vercel' | 'baml';\n }\n): BaseAgent {\n const framework = config.framework || 'langchain';\n\n switch (framework) {\n case 'langchain':\n return new LangChainAgent(config);\n case 'vercel':\n throw new Error('Vercel AI SDK support coming soon');\n case 'baml':\n throw new Error('BAML support coming soon');\n default:\n throw new Error(`Unknown framework: ${framework}`);\n }\n}","import type { \n BaseLanguageModelCallOptions\n} from '@langchain/core/language_models/base';\nimport type { BaseChatModel } from '@langchain/core/language_models/chat_models';\n\n/**\n * Framework-agnostic AI provider interface for multi-framework support\n */\nexport interface AIProvider {\n /**\n * Generate a response from the AI model\n */\n generate(\n prompt: string,\n options?: BaseLanguageModelCallOptions\n ): Promise<string>;\n\n /**\n * Stream a response from the AI model\n */\n stream?(\n prompt: string,\n options?: BaseLanguageModelCallOptions\n ): AsyncGenerator<string>;\n\n /**\n * Get the underlying model if available\n */\n getModel?(): BaseChatModel | unknown;\n}\n\n/**\n * LangChain AI provider implementation\n */\nexport class LangChainProvider implements AIProvider {\n constructor(private model: BaseChatModel) {}\n\n async generate(\n prompt: string,\n options?: BaseLanguageModelCallOptions\n ): Promise<string> {\n const result = await this.model.invoke(prompt, options);\n return typeof result === 'string' ? result : result.toString();\n }\n\n async *stream(\n prompt: string,\n options?: BaseLanguageModelCallOptions\n ): AsyncGenerator<string> {\n const stream = await this.model.stream(prompt, options);\n for await (const chunk of stream) {\n yield typeof chunk === 'string' ? chunk : chunk.toString();\n }\n }\n\n getModel(): BaseChatModel {\n return this.model;\n }\n}\n\n/**\n * Vercel AI SDK provider interface (forward-thinking)\n */\nexport interface VercelAIProvider extends AIProvider {\n /**\n * Use Vercel AI SDK's streamText function\n */\n streamText?(prompt: string, options?: unknown): Promise<unknown>;\n}\n\n/**\n * BAML provider interface (forward-thinking)\n */\nexport interface BAMLProvider extends AIProvider {\n /**\n * Execute a BAML function\n */\n executeFunction?(\n name: string,\n args: Record<string, unknown>\n ): Promise<unknown>;\n}","export const getSystemMessage = (\n accountId: string\n): string => `You are a helpful assistant managing Hashgraph Online HCS-10 connections, messages, HCS-2 registries, content inscription, and Hedera Hashgraph operations.\n\nYou have access to tools for:\n- HCS-10: registering agents, finding registered agents, initiating connections, listing active connections, sending messages over connections, and checking for new messages\n- HCS-2: creating registries, registering entries, updating entries, deleting entries, migrating registries, and querying registry contents\n- Inscription: inscribing content from URLs, files, or buffers, creating Hashinal NFTs, and retrieving inscriptions\n- Hedera Token Service (HTS): creating tokens, transferring tokens, airdropping tokens, and managing token operations\n\n*** IMPORTANT CONTEXT ***\nYou are currently operating as agent: ${accountId} on the Hashgraph Online network\nWhen users ask about \"my profile\", \"my account\", \"my connections\", etc., use this account ID: ${accountId}\n\n*** CRITICAL ENTITY HANDLING RULES ***\n- When users refer to entities (tokens, topics, accounts) with pronouns like \"it\", \"that\", \"the token/topic\", etc., ALWAYS use the most recently created entity of that type\n- Entity IDs look like \"0.0.XXXXXX\" and are stored in memory after creation\n- NEVER use example or placeholder IDs like \"0.0.123456\" - always use actual created entity IDs\n- Account ID ${accountId} is NOT a token - tokens and accounts are different entities\n\nRemember the connection numbers when listing connections, as users might refer to them.`;\n","import { ContentStorage } from '../memory/ContentStorage';\nimport { \n ContentStoreService, \n extractReferenceId, \n shouldUseReference,\n ContentResolverRegistry,\n type ContentStoreInterface, \n type ContentResolverInterface, \n type ReferenceResolutionResult \n} from '@hashgraphonline/standards-sdk';\nimport type { ContentReferenceConfig } from '../types/content-reference';\nimport { Logger } from '@hashgraphonline/standards-sdk';\n\n/**\n * Adapter to make ContentStorage compatible with ContentStoreInterface\n */\nclass ContentStorageAdapter implements ContentStoreInterface {\n constructor(private storage: ContentStorage) {}\n\n async storeContent(content: Buffer, metadata: any) {\n const contentRef = await this.storage.storeContent(content, metadata);\n return contentRef.referenceId;\n }\n\n async resolveReference(referenceId: string): Promise<ReferenceResolutionResult> {\n const result = await this.storage.resolveReference(referenceId);\n if (result.success && result.content) {\n const response: ReferenceResolutionResult = {\n content: result.content\n };\n if (result.metadata) {\n response.metadata = {\n ...(result.metadata.mimeType !== undefined && { mimeType: result.metadata.mimeType }),\n ...(result.metadata.fileName !== undefined && { fileName: result.metadata.fileName }),\n originalSize: result.metadata.sizeBytes\n };\n }\n return response;\n } else {\n throw new Error(result.error || 'Reference not found');\n }\n }\n\n async hasReference(referenceId: string) {\n return await this.storage.hasReference(referenceId);\n }\n\n async cleanupReference(referenceId: string) {\n await this.storage.cleanupReference(referenceId);\n }\n\n async getStats() {\n return await this.storage.getStats();\n }\n\n async updateConfig(config: any) {\n return await this.storage.updateConfig(config);\n }\n\n async performCleanup() {\n await this.storage.performCleanup();\n }\n\n async dispose() {\n return Promise.resolve(this.storage.dispose());\n }\n}\n\n/**\n * Content resolver implementation for dependency injection\n */\nclass ContentResolver implements ContentResolverInterface {\n constructor(private adapter: ContentStorageAdapter) {}\n\n async resolveReference(referenceId: string): Promise<ReferenceResolutionResult> {\n return await this.adapter.resolveReference(referenceId);\n }\n\n shouldUseReference(content: string | Buffer): boolean {\n return shouldUseReference(content);\n }\n\n extractReferenceId(input: string): string | null {\n return extractReferenceId(input);\n }\n}\n\n/**\n * Manages content store lifecycle and cross-package registration\n */\nexport class ContentStoreManager {\n private contentStorage: ContentStorage;\n private adapter: ContentStorageAdapter;\n private resolver: ContentResolver;\n private logger: Logger;\n private isRegistered = false;\n\n constructor(\n maxMessageStorage: number = 1000,\n referenceConfig?: Partial<ContentReferenceConfig>,\n logger?: Logger\n ) {\n this.logger = logger || {\n info: console.log,\n debug: console.log,\n warn: console.warn,\n error: console.error\n } as Logger;\n\n this.contentStorage = new ContentStorage(maxMessageStorage, referenceConfig);\n this.adapter = new ContentStorageAdapter(this.contentStorage);\n this.resolver = new ContentResolver(this.adapter);\n }\n\n /**\n * Initialize and register content storage for cross-package access\n */\n async initialize(): Promise<void> {\n if (this.isRegistered) {\n this.logger.warn('ContentStoreManager is already initialized');\n return;\n }\n\n try {\n await ContentStoreService.setInstance(this.adapter);\n ContentResolverRegistry.register(this.resolver);\n this.isRegistered = true;\n this.logger.info('ContentStoreManager initialized and registered for cross-package access');\n } catch (error) {\n this.logger.error('Failed to initialize ContentStoreManager:', error);\n throw error;\n }\n }\n\n /**\n * Get the underlying ContentStorage instance\n */\n getContentStorage(): ContentStorage {\n return this.contentStorage;\n }\n\n /**\n * Get storage statistics\n */\n async getStats() {\n return await this.contentStorage.getStats();\n }\n\n /**\n * Update configuration\n */\n async updateConfig(config: Partial<ContentReferenceConfig>) {\n return await this.contentStorage.updateConfig(config);\n }\n\n /**\n * Perform manual cleanup\n */\n async performCleanup() {\n return await this.contentStorage.performCleanup();\n }\n\n /**\n * Check if content should be stored as reference\n */\n shouldUseReference(content: Buffer | string): boolean {\n return this.contentStorage.shouldUseReference(content);\n }\n\n /**\n * Store content if it's large enough\n */\n async storeContentIfLarge(content: Buffer | string, metadata: any) {\n return await this.contentStorage.storeContentIfLarge(content, metadata);\n }\n\n /**\n * Cleanup and unregister\n */\n async dispose(): Promise<void> {\n if (this.isRegistered) {\n this.contentStorage.dispose();\n ContentStoreService.dispose();\n ContentResolverRegistry.unregister();\n this.isRegistered = false;\n this.logger.info('ContentStoreManager disposed and unregistered');\n }\n }\n\n /**\n * Check if the manager is initialized\n */\n isInitialized(): boolean {\n return this.isRegistered;\n }\n}","import { StructuredTool } from '@langchain/core/tools';\nimport { z } from 'zod';\nimport { ChatOpenAI } from '@langchain/openai';\nimport type { EntityAssociation } from '../memory/SmartMemoryManager';\n\nconst ResolveEntitiesSchema = z.object({\n message: z.string().describe('The message containing entity references to resolve'),\n entities: z.array(z.object({\n entityId: z.string(),\n entityName: z.string(),\n entityType: z.string(),\n })).describe('Available entities in memory'),\n});\n\nconst ExtractEntitiesSchema = z.object({\n response: z.string().describe('Agent response text to extract entities from'),\n userMessage: z.string().describe('Original user message for context'),\n});\n\nexport class ResolveEntitiesTool extends StructuredTool {\n name = 'resolve_entities';\n description = 'Resolves entity references like \"the topic\", \"it\", \"that\" to actual entity IDs';\n schema = ResolveEntitiesSchema;\n \n private llm: ChatOpenAI;\n \n constructor(apiKey: string, modelName = 'gpt-4o-mini') {\n super();\n this.llm = new ChatOpenAI({\n apiKey,\n modelName,\n temperature: 0,\n });\n }\n \n async _call(input: z.infer<typeof ResolveEntitiesSchema>): Promise<string> {\n const { message, entities } = input;\n \n if (!entities || entities.length === 0) {\n return message;\n }\n \n const byType = this.groupEntitiesByType(entities);\n const context = this.buildEntityContext(byType);\n \n const prompt = `Task: Replace entity references with IDs.\n\n${context}\n\nMessage: \"${message}\"\n\nRules:\n- \"the topic\" or \"that topic\" → replace with most recent topic ID\n- \"the token\" or \"that token\" → replace with most recent token ID\n- \"it\" or \"that\" after action verb → replace with most recent entity ID\n- \"airdrop X\" without token ID → add most recent token ID as first parameter\n- Token operations without explicit token → use most recent token ID\n\nExamples:\n- \"submit on the topic\" → \"submit on 0.0.6543472\"\n- \"airdrop the token\" → \"airdrop 0.0.123456\"\n- \"airdrop 10 to 0.0.5842697\" → \"airdrop 0.0.123456 10 to 0.0.5842697\"\n- \"mint 100\" → \"mint 0.0.123456 100\"\n\nReturn ONLY the resolved message:`;\n \n try {\n const response = await this.llm.invoke(prompt);\n return (response.content as string).trim();\n } catch (error) {\n console.error('[ResolveEntitiesTool] Failed:', error);\n return message;\n }\n }\n \n private groupEntitiesByType(entities: EntityGroup): GroupedEntities {\n return entities.reduce((acc, entity) => {\n if (!acc[entity.entityType]) {\n acc[entity.entityType] = [];\n }\n acc[entity.entityType].push(entity);\n return acc;\n }, {} as GroupedEntities);\n }\n \n private buildEntityContext(groupedEntities: GroupedEntities): string {\n let context = 'Available entities:\\n';\n for (const [type, list] of Object.entries(groupedEntities)) {\n const recent = list[0];\n context += `- Most recent ${type}: \"${recent.entityName}\" = ${recent.entityId}\\n`;\n }\n return context;\n }\n}\n\nexport class ExtractEntitiesTool extends StructuredTool {\n name = 'extract_entities';\n description = 'Extracts newly created entities from agent responses';\n schema = ExtractEntitiesSchema;\n \n private llm: ChatOpenAI;\n \n constructor(apiKey: string, modelName = 'gpt-4o-mini') {\n super();\n this.llm = new ChatOpenAI({\n apiKey,\n modelName,\n temperature: 0,\n });\n }\n \n async _call(input: z.infer<typeof ExtractEntitiesSchema>): Promise<string> {\n const { response, userMessage } = input;\n \n const prompt = `Extract ONLY newly created entities from this response.\n\nUser asked: \"${userMessage.substring(0, 200)}\"\nResponse: ${response.substring(0, 3000)}\n\nLook for:\n- Success messages with new entity IDs\n- Words like \"created\", \"new\", \"successfully\" followed by entity IDs\n\nReturn JSON array of created entities:\n[{\"id\": \"0.0.XXX\", \"name\": \"name\", \"type\": \"topic|token|account\"}]\n\nIf none created, return: []\n\nJSON:`;\n \n try {\n const llmResponse = await this.llm.invoke(prompt);\n const content = llmResponse.content as string;\n const match = content.match(/\\[[\\s\\S]*?\\]/);\n if (match) {\n return match[0];\n }\n return '[]';\n } catch (error) {\n console.error('[ExtractEntitiesTool] Failed:', error);\n return '[]';\n }\n }\n}\n\nexport function createEntityTools(apiKey: string, modelName = 'gpt-4o-mini'): {\n resolveEntities: ResolveEntitiesTool;\n extractEntities: ExtractEntitiesTool;\n} {\n return {\n resolveEntities: new ResolveEntitiesTool(apiKey, modelName),\n extractEntities: new ExtractEntitiesTool(apiKey, modelName),\n };\n}\n\ninterface EntityReference {\n entityId: string;\n entityName: string;\n entityType: string;\n}\n\ntype EntityGroup = EntityReference[];\n\ntype GroupedEntities = Record<string, EntityGroup>;\n\ninterface ExtractedEntity {\n id: string;\n name: string;\n type: string;\n}","import {\n ServerSigner,\n getAllHederaCorePlugins,\n BasePlugin,\n} from 'hedera-agent-kit';\nimport {\n HederaMirrorNode,\n Logger,\n type NetworkType,\n} 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 { HumanMessage, AIMessage } 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 { PrivateKey } from '@hashgraph/sdk';\nimport { getSystemMessage } from './config/system-message';\nimport type { MCPServerConfig, MCPConnectionStatus } from './mcp/types';\nimport { ContentStoreManager } from './services/ContentStoreManager';\nimport { SmartMemoryManager, type SmartMemoryConfig } from './memory';\nimport {\n createEntityTools,\n ResolveEntitiesTool,\n ExtractEntitiesTool,\n} from './tools/EntityResolverTool';\n\nexport type ToolDescriptor = {\n name: string;\n namespace?: string;\n};\n\nexport type ChatHistoryItem = {\n type: 'human' | 'ai';\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 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 privateKeyInstance = await this.detectPrivateKeyType(\n accountId!,\n privateKey!,\n network\n );\n\n const serverSigner = new ServerSigner(\n accountId!,\n privateKeyInstance,\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 const allPlugins = this.preparePlugins();\n const agentConfig = this.createAgentConfig(serverSigner, llm, allPlugins);\n\n this.agent = createAgent(agentConfig);\n\n this.configureHCS10Plugin(allPlugins);\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 await this.agent.boot();\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('Agent not initialized. Call initialize() first.');\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 = this.memoryManager\n ? await this.resolveEntitiesInMessage(message)\n : message;\n\n const messages = chatHistory.map((msg) => {\n if (msg.type === 'human') {\n return new HumanMessage(msg.content);\n } else {\n return new AIMessage(msg.content);\n }\n });\n\n const context: ConversationContext = {\n messages,\n };\n\n const response = await this.agent.chat(resolvedMessage, context);\n\n if (this.memoryManager) {\n await this.extractAndStoreEntities(response, message);\n }\n\n this.logger.info('Message processed successfully');\n\n return response;\n } catch (error) {\n this.logger.error('Error processing message:', 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\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 * Detect the private key type by querying the account info from mirror node\n * @param {string} accountId - The Hedera account ID\n * @param {string} privateKey - The private key string\n * @param {NetworkType} network - The Hedera Hashgraph\n * @returns {Promise<PrivateKey>} The appropriate PrivateKey instance\n */\n private async detectPrivateKeyType(\n accountId: string,\n privateKey: string,\n network: NetworkType\n ): Promise<PrivateKey> {\n const mirrorNode = new HederaMirrorNode(network as 'testnet' | 'mainnet');\n const accountInfo = await mirrorNode.requestAccount(accountId);\n\n const keyType = accountInfo?.key?._type || '';\n\n if (keyType?.toLowerCase()?.includes('ecdsa')) {\n return PrivateKey.fromStringECDSA(privateKey);\n } else {\n return PrivateKey.fromStringED25519(privateKey);\n }\n }\n\n /**\n * Resolve entity references using LLM-based resolver\n * @param content - Message content to resolve\n * @returns Resolved message content with entity IDs replaced\n */\n private async resolveEntitiesInMessage(content: string): Promise<string> {\n if (!this.memoryManager || !this.entityTools) {\n return content;\n }\n\n try {\n const entities = this.memoryManager.getEntityAssociations();\n\n if (entities.length === 0) {\n this.logger.info('No entities in memory, skipping resolution');\n return content;\n }\n\n this.logger.info(\n `Starting LLM-based entity resolution for: \"${content.substring(\n 0,\n 100\n )}...\"`\n );\n\n const resolvedContent = await this.entityTools.resolveEntities.call({\n message: content,\n entities: entities.map((e) => ({\n entityId: e.entityId,\n entityName: e.entityName,\n entityType: e.entityType,\n })),\n });\n\n if (resolvedContent !== content) {\n this.logger.info(\n `Entity resolution completed. Original: \"${content}\" -> Resolved: \"${resolvedContent}\"`\n );\n }\n\n return resolvedContent;\n } catch (error) {\n this.logger.error('Entity resolution failed:', error);\n throw error;\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 this.logger.info(\n `Storing entity: ${entity.name} (${entity.type}) -> ${entity.id}`\n );\n\n const transactionId = this.extractTransactionId(response);\n this.memoryManager.storeEntityAssociation(\n entity.id,\n entity.name,\n entity.type,\n transactionId\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 return (response as { transactionId?: string }).transactionId;\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 return String(response.output);\n }\n\n return JSON.stringify(response);\n }\n}\n","import type { MCPServerConfig } from './types';\n\n/**\n * Common MCP server configurations for easy setup\n */\nexport const MCPServers = {\n /**\n * Filesystem server for file operations\n */\n filesystem: (path: string): MCPServerConfig => ({\n name: 'filesystem',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-filesystem', path],\n transport: 'stdio',\n autoConnect: true,\n additionalContext: 'This server provides access to files and directories in the current working directory.',\n toolDescriptions: {\n list_directory: 'Use this tool when users ask about files in the \"current directory\" or \"working directory\".',\n read_file: 'Use this tool when users ask to see or check files in the current directory.',\n },\n }),\n\n /**\n * GitHub server for repository operations\n */\n github: (token?: string): MCPServerConfig => ({\n name: 'github',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-github'],\n ...(token && { env: { GITHUB_TOKEN: token } }),\n transport: 'stdio',\n autoConnect: true,\n }),\n\n /**\n * Slack server for messaging operations\n */\n slack: (token: string): MCPServerConfig => ({\n name: 'slack',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-slack'],\n env: { SLACK_TOKEN: token },\n transport: 'stdio',\n autoConnect: true,\n }),\n\n /**\n * Google Drive server for document operations\n */\n googleDrive: (credentials: string): MCPServerConfig => ({\n name: 'google-drive',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-google-drive'],\n env: { GOOGLE_CREDENTIALS: credentials },\n transport: 'stdio',\n autoConnect: true,\n }),\n\n /**\n * PostgreSQL server for database operations\n */\n postgres: (connectionString: string): MCPServerConfig => ({\n name: 'postgres',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-postgres', connectionString],\n transport: 'stdio',\n autoConnect: true,\n }),\n\n /**\n * SQLite server for database operations\n */\n sqlite: (dbPath: string): MCPServerConfig => ({\n name: 'sqlite',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-sqlite', dbPath],\n transport: 'stdio',\n autoConnect: true,\n }),\n\n /**\n * Custom server configuration\n */\n custom: (config: MCPServerConfig): MCPServerConfig => config,\n};\n\n/**\n * Validate MCP server configuration\n */\nexport function validateServerConfig(config: MCPServerConfig): string[] {\n const errors: string[] = [];\n\n if (!config.name) {\n errors.push('Server name is required');\n }\n\n if (!config.command) {\n errors.push('Server command is required');\n }\n\n if (!config.args || !Array.isArray(config.args)) {\n errors.push('Server args must be an array');\n }\n\n if (config.transport && !['stdio', 'http', 'websocket'].includes(config.transport)) {\n errors.push('Invalid transport type. Must be stdio, http, or websocket');\n }\n\n return errors;\n}\n\n/**\n * Create a typed MCP configuration for ConversationalAgent\n */\nexport function createMCPConfig(servers: MCPServerConfig[], autoConnect = true): { mcpServers: MCPServerConfig[] } {\n return {\n mcpServers: servers.map(server => ({\n ...server,\n autoConnect: server.autoConnect ?? autoConnect,\n })),\n };\n}"],"names":["HCS10Plugin","BasePlugin","constructor","super","arguments","this","id","name","description","version","author","namespace","tools","initialize","context","hederaKit","config","stateManager","appConfig","OpenConvaiState","accountId","signer","getAccountId","toString","inboundTopicId","outboundTopicId","opKey","getOperatorPrivateKey","privateKey","toStringRaw","String","hcs10Client","HCS10Client","network","operatorId","operatorPrivateKey","logLevel","profileResponse","retrieveProfile","success","topicInfo","inboundTopic","outboundTopic","profileError","logger","warn","setCurrentAgent","info","getConnectionsManager","initializeConnectionsManager","cmError","initializeTools","error","Error","hcs10Builder","HCS10Builder","RegisterAgentTool","FindRegistrationsTool","RetrieveProfileTool","InitiateConnectionTool","ListConnectionsTool","SendMessageToConnectionTool","CheckMessagesTool","ConnectionMonitorTool","ManageConnectionRequestsTool","AcceptConnectionRequestTool","ListUnapprovedConnectionRequestsTool","getTools","getStateManager","cleanup","HCS2Plugin","hcs2Builder","HCS2Builder","CreateRegistryTool","RegisterEntryTool","UpdateEntryTool","DeleteEntryTool","MigrateRegistryTool","QueryRegistryTool","InscribePlugin","inscriberBuilder","InscriberBuilder","InscribeFromUrlTool","InscribeFromFileTool","InscribeFromBufferTool","InscribeHashinalTool","RetrieveInscriptionTool","AccountBuilder","BaseServiceBuilder","transferHbar","params","isUserInitiated","clearNotes","transaction","TransferTransaction","transfers","length","netZeroInTinybars","BigNumber","userTransferProcessedForScheduling","kit","userAccountId","operationalMode","receiverTransfer","amountValue","amount","amountBigNum","isPositive","recipientAccountId","AccountId","fromString","roundedAmount","toFixed","ROUND_DOWN","sdkHbarAmount","Hbar","addNote","addHbarTransfer","negated","processedTransfers","transferInput","push","hbar","tinybarsContribution","toTinybars","plus","isZero","lastTransfer","adjustment","dividedBy","adjustedRounded","transfer","memo","setTransactionMemo","setCurrentTransaction","HbarTransferInputSchema","z","object","string","describe","union","number","TransferHbarZodSchemaCore","array","min","optional","TransferHbarTool","BaseHederaTransactionTool","specificInputSchema","getServiceBuilder","callBuilderMethod","builder","specificArgs","AirdropToolWrapper","StructuredTool","originalTool","agentKit","schema","tokenId","recipients","Logger","module","_call","input","decimals","getTokenInfo","convertedRecipients","map","recipient","humanAmount","parseFloat","smallestUnitAmount","convertToSmallestUnits","convertedInput","Math","floor","pow","queryTokenInfo","mirrorNode","tokenData","parseInt","mirrorNodeUrl","response","fetch","ok","json","HbarPlugin","originalAirdropTool","airdropTool","HederaAirdropTokenTool","wrappedAirdropTool","shutdown","ContentAwareAgentExecutor","AgentExecutor","BaseAgent","initialized","silent","debug","getCore","filterTools","filtered","filter","filtering","namespaceWhitelist","tool","includes","toolBlacklist","toolPredicate","buildSystemPrompt","parts","userAccId","execution","messaging","systemPreamble","scheduleUserTransactionsInBytesMode","conciseMode","systemPostamble","join","isReady","MCPContentProcessor","contentStorage","analyzeResponse","contents","totalSize","extractContentFromResponse","reduce","sum","content","sizeBytes","largestContentSize","max","shouldProcess","some","shouldUseReference","JSON","stringify","processResponse","serverName","toolName","analysis","wasProcessed","createReferencedResponse","errors","message","obj","Array","isArray","forEach","item","record","type","text","globalThis","Buffer","byteLength","mimeType","detectMimeType","data","ceil","resource","resourceStr","Object","values","value","originalResponse","processedResponse","deepClone","referenceCreated","totalReferenceSize","contentInfo","contentBuffer","from","metadata","contentType","mapMimeTypeToContentType","source","mcpToolName","tags","reference","storeContentIfLarge","replaceContentInResponse","createLightweightReference","result","originalSize","referenceId","preview","size","format","_isReference","oldContent","newContent","i","key","keys","trim","startsWith","Date","getTime","cloned","hasOwnProperty","MCPClientManager","clients","Map","contentProcessor","connectServer","isServerConnected","connected","transport","StdioClientTransport","command","args","env","client","Client","capabilities","connect","set","toolsWithServer","listTools","executeTool","get","callTool","processed","disconnectAll","close","clear","getAllTools","allTools","getServerTools","has","getConnectedServers","enableContentProcessing","disableContentProcessing","isContentProcessingEnabled","analyzeResponseContent","convertMCPToolToLangChain","mcpManager","serverConfig","zodSchema","jsonSchemaToZod","inputSchema","sanitizedName","replace","toolDescriptions","additionalContext","DynamicStructuredTool","func","async","responseText","responseBuffer","MCP_REFERENCE_THRESHOLD","contentStore","ContentStoreService","getInstance","storeContent","storeError","errorMessage","schemaObj","convertType","properties","shape","entries","zodType","required","unknown","enum","minimum","maximum","int","boolean","items","passthrough","_TokenCounter","modelName","encoding","encoding_for_model","countTokens","encode","split","countMessageTokens","getMessageRole","MESSAGE_OVERHEAD","ROLE_OVERHEAD","countMessagesTokens","messages","total","estimateSystemPromptTokens","systemPrompt","estimateContextSize","_getType","getModelName","dispose","free","TokenCounter","_MemoryWindow","maxTokens","DEFAULT_MAX_TOKENS","reserveTokens","DEFAULT_RESERVE_TOKENS","tokenCounter","systemPromptTokens","addMessage","prunedMessages","getCurrentTokenCount","pop","pruneToFit","added","currentTokenCount","remainingCapacity","getRemainingTokenCapacity","targetTokens","batchSize","PRUNING_BATCH_SIZE","prunedMessage","shift","messageTokens","canAddMessage","wouldExceedReserve","getMessages","setSystemPrompt","getSystemPrompt","getConfig","currentTokens","messageCount","updateLimits","getStats","capacity","usagePercentage","totalMessages","round","canAcceptMore","MemoryWindow","ReferenceIdGenerator","generateId","hash","createHash","update","digest","isValidReferenceId","test","extractReferenceId","refFormatMatch","match","formatReference","generateTestId","testSeed","now","DEFAULT_CONTENT_REFERENCE_CONFIG","sizeThresholdBytes","maxAgeMs","maxReferences","maxTotalStorageBytes","enableAutoCleanup","cleanupIntervalMs","enablePersistence","storageBackend","cleanupPolicies","recent","priority","userContent","agentGenerated","default","ContentReferenceError","suggestedActions","_ContentStorage","maxStorage","DEFAULT_MAX_STORAGE","referenceConfig","idCounter","referenceStats","activeReferences","totalStorageBytes","recentlyCleanedUp","totalResolutions","failedResolutions","averageContentSize","storageUtilization","performanceMetrics","averageCreationTimeMs","averageResolutionTimeMs","averageCleanupTimeMs","creationTimes","resolutionTimes","cleanupTimes","startReferenceCleanupTimer","storeMessages","stored","dropped","storedMessages","storedAt","getRecentMessages","count","startIndex","slice","searchMessages","query","options","caseSensitive","limit","useRegex","matches","regex","RegExp","searchTerm","toLowerCase","getMessagesFromTimeRange","startTime","endTime","getStorageStats","oldestMessageTime","newestMessageTime","maxStorageLimit","getTotalStoredMessages","updateStorageLimit","newLimit","getMessagesByType","messageType","currentUsage","utilizationPercentage","getRecentMessagesByTime","minutes","cutoffTime","exportMessages","toISOString","isBuffer","buffer","storeMetadata","detectContentType","fileName","customMetadata","fullMetadata","createdAt","lastAccessedAt","accessCount","storedContent","state","expirationTime","calculateExpirationTime","expiresAt","updateStatsAfterStore","enforceReferenceStorageLimits","createContentPreview","referenceMetadata","duration","recordPerformanceMetric","resolveReference","errorType","hasReference","cleanupReference","delete","updateReferenceStorageStats","calculateAverage","updateConfig","cleanupTimer","clearInterval","performCleanup","cleanedUp","toCleanup","shouldCleanup","ageMs","getCleanupPolicy","sort","a","b","aContent","bContent","aPriority","sortedByAge","excessCount","getReferenceConfig","policy","contentStr","maxLength","parsed","parse","substring","mostAccessedId","maxAccess","mostAccessedReferenceId","timeMs","metrics","times","time","setInterval","ContentStorage","IS_ENTITY_ASSOCIATION_FLAG","_SmartMemoryManager","DEFAULT_CONFIG","_contentStorage","storageLimit","memoryWindow","clearStorage","searchHistory","getRecentHistory","getMemoryStats","windowStats","totalActiveMessages","getOverallStats","memoryStats","storageStats","activeMemory","storage","totalMessagesManaged","activeMemoryUtilization","newConfig","getHistoryFromTimeRange","getHistoryByType","getRecentHistoryByTime","exportState","activeMessages","msg","getContextSummary","includeStoredContext","summary","activeMessageCount","recentMessages","memoryUtilization","hasStoredHistory","recentStoredMessages","performMaintenance","storeEntityAssociation","entityId","entityName","entityType","transactionId","sanitizedEntityId","sanitizedEntityName","sanitizedEntityType","association","isEntityAssociation","entityMessage","additional_kwargs","_error","resolveEntityReference","sanitizedQuery","fuzzyMatch","safeLimit","isEntityIdQuery","searchResults","associations","fuzzyQueries","Boolean","fuzzyQuery","fuzzyResults","uniqueAssociations","assoc","index","arr","findIndex","getEntityAssociations","searchQuery","_parseError","d","aTime","SmartMemoryManager","LangChainAgent","systemMessage","mcpConnectionStatus","boot","createAgentKit","ai","process","OPENAI_MODEL_NAME","tokenTracker","TokenUsageCallbackHandler","getAggregatedLangChainTools","mcp","servers","autoConnect","initializeMCP","smartMemory","toolsCount","createExecutor","chat","executor","contextLength","HumanMessage","import","invoke","chat_history","output","notes","intermediateSteps","toolCalls","step","action","toolInput","observation","tool_calls","parsedSteps","isJSON","AIMessage","tokenUsage","getLatestTokenUsage","cost","calculateTokenCostSync","finalMemoryStats","handleError","switchMode","mode","getUsageStats","promptTokens","completionTokens","totalTokens","totalCost","usage","getTotalTokenUsage","getUsageLog","getTokenUsageHistory","clearUsageStats","reset","getMCPConnectionStatus","plugins","getAllHederaCorePlugins","extensions","HederaAgentKit","mirrorConfig","llm","provider","getModel","apiKey","OPENAI_API_KEY","isGPT5Model","ChatOpenAI","callbacks","temperature","prompt","ChatPromptTemplate","fromMessages","MessagesPlaceholder","langchainTools","agent","createOpenAIToolsAgent","verbose","returnIntermediateSteps","userFriendlyMessage","userFriendlyOutput","errorResponse","status","mcpTool","langchainTool","connectMCPServers","connectServerInBackground","setTimeout","str","trimmed","endsWith","createAgent","framework","LangChainProvider","model","generate","stream","chunk","getSystemMessage","ContentStorageAdapter","Promise","resolve","ContentResolver","adapter","ContentStoreManager","maxMessageStorage","isRegistered","console","log","resolver","setInstance","ContentResolverRegistry","register","getContentStorage","unregister","isInitialized","ResolveEntitiesSchema","entities","ExtractEntitiesSchema","userMessage","ResolveEntitiesTool","byType","groupEntitiesByType","buildEntityContext","acc","entity","groupedEntities","list","ExtractEntitiesTool","llmResponse","createEntityTools","resolveEntities","extractEntities","DEFAULT_MODEL_NAME","DEFAULT_NETWORK","DEFAULT_OPERATIONAL_MODE","ConversationalAgent","hcs10Plugin","hcs2Plugin","inscribePlugin","hbarPlugin","disableLogging","entityMemoryEnabled","openAIApiKey","memoryManager","entityMemoryConfig","entityTools","openAIModelName","llmProvider","validateOptions","privateKeyInstance","detectPrivateKeyType","serverSigner","ServerSigner","ChatAnthropic","allPlugins","preparePlugins","agentConfig","createAgentConfig","configureHCS10Plugin","contentStoreManager","cfg","originalPredicate","userPredicate","toolFilter","mcpServers","connectMCP","getPlugin","getAgent","getConversationalAgent","processMessage","chatHistory","resolvedMessage","resolveEntitiesInMessage","extractAndStoreEntities","additionalPlugins","enabledPlugins","standardPlugins","corePlugins","enabledSet","Set","plugin","customSystemMessagePreamble","customSystemMessagePostamble","mirrorNodeConfig","scheduleUserTransactions","hcs10","find","p","withPlugins","withHTS","withHCS2","withHCS10","withInscribe","withAccount","withFileService","withConsensusService","withSmartContract","withAllStandards","minimal","withMCP","HederaMirrorNode","accountInfo","requestAccount","keyType","_type","PrivateKey","fromStringECDSA","fromStringED25519","resolvedContent","call","e","originalMessage","extractResponseText","entitiesJson","extractTransactionId","parseError","catch","then","isMCPServerConnected","filesystem","path","list_directory","read_file","github","token","GITHUB_TOKEN","slack","SLACK_TOKEN","googleDrive","credentials","GOOGLE_CREDENTIALS","postgres","connectionString","sqlite","dbPath","custom","server"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","sources":["../../src/plugins/hcs-10/HCS10Plugin.ts","../../src/plugins/hcs-2/HCS2Plugin.ts","../../src/plugins/inscribe/InscribePlugin.ts","../../src/plugins/hbar/AccountBuilder.ts","../../src/plugins/hbar/TransferHbarTool.ts","../../src/plugins/hbar/AirdropToolWrapper.ts","../../src/plugins/hbar/HbarPlugin.ts","../../src/langchain/ContentAwareAgentExecutor.ts","../../src/base-agent.ts","../../src/mcp/ContentProcessor.ts","../../src/mcp/MCPClientManager.ts","../../src/mcp/adapters/langchain.ts","../../src/memory/TokenCounter.ts","../../src/memory/MemoryWindow.ts","../../src/memory/ReferenceIdGenerator.ts","../../src/types/content-reference.ts","../../src/memory/ContentStorage.ts","../../src/memory/SmartMemoryManager.ts","../../src/langchain-agent.ts","../../src/agent-factory.ts","../../src/providers.ts","../../src/config/system-message.ts","../../src/services/ContentStoreManager.ts","../../src/tools/EntityResolverTool.ts","../../src/conversational-agent.ts","../../src/mcp/helpers.ts"],"sourcesContent":["import {\n GenericPluginContext,\n HederaTool,\n BasePlugin,\n HederaAgentKit,\n} from 'hedera-agent-kit';\nimport {\n IStateManager,\n OpenConvaiState,\n HCS10Builder,\n RegisterAgentTool,\n FindRegistrationsTool,\n InitiateConnectionTool,\n ListConnectionsTool,\n SendMessageToConnectionTool,\n CheckMessagesTool,\n ConnectionMonitorTool,\n ManageConnectionRequestsTool,\n AcceptConnectionRequestTool,\n RetrieveProfileTool,\n ListUnapprovedConnectionRequestsTool,\n} from '@hashgraphonline/standards-agent-kit';\nimport { HCS10Client } from '@hashgraphonline/standards-sdk';\n\nexport class HCS10Plugin extends BasePlugin {\n id = 'hcs-10';\n name = 'HCS-10 Plugin';\n description =\n 'HCS-10 agent tools for decentralized agent registration, connections, and messaging on Hedera';\n version = '1.0.0';\n author = 'Hashgraph Online';\n namespace = 'hcs10';\n\n private stateManager?: IStateManager;\n private tools: HederaTool[] = [];\n appConfig?: Record<string, unknown>;\n\n override async initialize(context: GenericPluginContext): Promise<void> {\n await super.initialize(context);\n\n const hederaKit = context.config.hederaKit as HederaAgentKit;\n if (!hederaKit) {\n this.context.logger.warn(\n 'HederaKit not found in context. HCS-10 tools will not be available.'\n );\n return;\n }\n\n try {\n this.stateManager =\n (context.stateManager as IStateManager) ||\n (context.config.stateManager as IStateManager) ||\n (this.appConfig?.stateManager as IStateManager) ||\n new OpenConvaiState();\n\n const accountId = hederaKit.signer.getAccountId().toString();\n let inboundTopicId = '';\n let outboundTopicId = '';\n\n try {\n const opKey = hederaKit.signer.getOperatorPrivateKey() as {\n toString?: () => string;\n toStringRaw?: () => string;\n };\n const privateKey = typeof opKey?.toStringRaw === 'function'\n ? opKey.toStringRaw()\n : typeof opKey?.toString === 'function'\n ? opKey.toString()\n : String(opKey);\n\n const hcs10Client = new HCS10Client({\n network: hederaKit.network as 'mainnet' | 'testnet',\n operatorId: accountId,\n operatorPrivateKey: privateKey,\n logLevel: 'error',\n });\n\n const profileResponse = await hcs10Client.retrieveProfile(accountId);\n if (profileResponse.success && profileResponse.topicInfo) {\n inboundTopicId = profileResponse.topicInfo.inboundTopic;\n outboundTopicId = profileResponse.topicInfo.outboundTopic;\n }\n } catch (profileError) {\n this.context.logger.warn(\n 'Could not retrieve profile topics:',\n profileError\n );\n }\n\n this.stateManager.setCurrentAgent({\n name: `Agent ${accountId}`,\n accountId: accountId,\n inboundTopicId,\n outboundTopicId,\n privateKey: ((): string => {\n const opKey = hederaKit.signer.getOperatorPrivateKey() as {\n toString?: () => string;\n toStringRaw?: () => string;\n };\n return typeof opKey?.toStringRaw === 'function'\n ? opKey.toStringRaw()\n : typeof opKey?.toString === 'function'\n ? opKey.toString()\n : String(opKey);\n })(),\n });\n\n this.context.logger.info(\n `Set current agent: ${accountId} with topics ${inboundTopicId}/${outboundTopicId}`\n );\n\n if (this.stateManager && !this.stateManager.getConnectionsManager()) {\n try {\n const opKey = hederaKit.signer.getOperatorPrivateKey() as {\n toString?: () => string;\n toStringRaw?: () => string;\n };\n const privateKey = typeof opKey?.toStringRaw === 'function'\n ? opKey.toStringRaw()\n : typeof opKey?.toString === 'function'\n ? opKey.toString()\n : String(opKey);\n const hcs10Client = new HCS10Client({\n network: hederaKit.network as 'mainnet' | 'testnet',\n operatorId: accountId,\n operatorPrivateKey: privateKey,\n logLevel: 'error',\n });\n\n this.stateManager.initializeConnectionsManager(hcs10Client as any);\n this.context.logger.info(\n 'ConnectionsManager initialized in HCS10Plugin'\n );\n } catch (cmError) {\n this.context.logger.warn('Could not initialize ConnectionsManager:', cmError);\n }\n }\n\n this.initializeTools();\n\n this.context.logger.info('HCS-10 Plugin initialized successfully');\n } catch (error) {\n this.context.logger.error('Failed to initialize HCS-10 plugin:', error);\n }\n }\n\n private initializeTools(): void {\n if (!this.stateManager) {\n throw new Error('StateManager must be initialized before creating tools');\n }\n\n const hederaKit = this.context.config.hederaKit as HederaAgentKit;\n if (!hederaKit) {\n throw new Error('HederaKit not found in context config');\n }\n\n const hcs10Builder = new HCS10Builder(hederaKit, this.stateManager);\n\n this.tools = [\n new RegisterAgentTool({\n hederaKit: hederaKit,\n hcs10Builder: hcs10Builder,\n logger: this.context.logger,\n }),\n new FindRegistrationsTool({\n hederaKit: hederaKit,\n hcs10Builder: hcs10Builder,\n logger: this.context.logger,\n }),\n new RetrieveProfileTool({\n hederaKit: hederaKit,\n hcs10Builder: hcs10Builder,\n logger: this.context.logger,\n }),\n new InitiateConnectionTool({\n hederaKit: hederaKit,\n hcs10Builder: hcs10Builder,\n logger: this.context.logger,\n }),\n new ListConnectionsTool({\n hederaKit: hederaKit,\n hcs10Builder: hcs10Builder,\n logger: this.context.logger,\n }),\n new SendMessageToConnectionTool({\n hederaKit: hederaKit,\n hcs10Builder: hcs10Builder,\n logger: this.context.logger,\n }),\n new CheckMessagesTool({\n hederaKit: hederaKit,\n hcs10Builder: hcs10Builder,\n logger: this.context.logger,\n }),\n new ConnectionMonitorTool({\n hederaKit: hederaKit,\n hcs10Builder: hcs10Builder,\n logger: this.context.logger,\n }),\n new ManageConnectionRequestsTool({\n hederaKit: hederaKit,\n hcs10Builder: hcs10Builder,\n logger: this.context.logger,\n }),\n new AcceptConnectionRequestTool({\n hederaKit: hederaKit,\n hcs10Builder: hcs10Builder,\n logger: this.context.logger,\n }),\n new ListUnapprovedConnectionRequestsTool({\n hederaKit: hederaKit,\n hcs10Builder: hcs10Builder,\n logger: this.context.logger,\n }),\n ];\n }\n\n getTools(): HederaTool[] {\n return this.tools;\n }\n\n getStateManager(): IStateManager | undefined {\n return this.stateManager;\n }\n\n override async cleanup(): Promise<void> {\n this.tools = [];\n delete this.stateManager;\n if (this.context?.logger) {\n this.context.logger.info('HCS-10 Plugin cleaned up');\n }\n }\n}\n","import {\n GenericPluginContext,\n HederaTool,\n BasePlugin,\n HederaAgentKit,\n} from 'hedera-agent-kit';\nimport {\n HCS2Builder,\n CreateRegistryTool,\n RegisterEntryTool,\n UpdateEntryTool,\n DeleteEntryTool,\n MigrateRegistryTool,\n QueryRegistryTool,\n} from '@hashgraphonline/standards-agent-kit';\n\n/**\n * Plugin providing HCS-2 registry management tools\n */\nexport class HCS2Plugin extends BasePlugin {\n id = 'hcs-2';\n name = 'HCS-2 Plugin';\n description =\n 'HCS-2 registry management tools for decentralized registries on Hedera';\n version = '1.0.0';\n author = 'Hashgraph Online';\n namespace = 'hcs2';\n\n private tools: HederaTool[] = [];\n\n override async initialize(context: GenericPluginContext): Promise<void> {\n await super.initialize(context);\n\n const hederaKit = context.config.hederaKit as HederaAgentKit;\n if (!hederaKit) {\n this.context.logger.warn(\n 'HederaKit not found in context. HCS-2 tools will not be available.'\n );\n return;\n }\n\n try {\n this.initializeTools();\n\n this.context.logger.info(\n 'HCS-2 Plugin initialized successfully'\n );\n } catch (error) {\n this.context.logger.error(\n 'Failed to initialize HCS-2 plugin:',\n error\n );\n }\n }\n\n private initializeTools(): void {\n const hederaKit = this.context.config.hederaKit as HederaAgentKit;\n if (!hederaKit) {\n throw new Error('HederaKit not found in context config');\n }\n\n const hcs2Builder = new HCS2Builder(hederaKit);\n\n this.tools = [\n new CreateRegistryTool({\n hederaKit: hederaKit,\n hcs2Builder: hcs2Builder,\n logger: this.context.logger,\n }),\n new RegisterEntryTool({\n hederaKit: hederaKit,\n hcs2Builder: hcs2Builder,\n logger: this.context.logger,\n }),\n new UpdateEntryTool({\n hederaKit: hederaKit,\n hcs2Builder: hcs2Builder,\n logger: this.context.logger,\n }),\n new DeleteEntryTool({\n hederaKit: hederaKit,\n hcs2Builder: hcs2Builder,\n logger: this.context.logger,\n }),\n new MigrateRegistryTool({\n hederaKit: hederaKit,\n hcs2Builder: hcs2Builder,\n logger: this.context.logger,\n }),\n new QueryRegistryTool({\n hederaKit: hederaKit,\n hcs2Builder: hcs2Builder,\n logger: this.context.logger,\n }),\n ];\n }\n\n getTools(): HederaTool[] {\n return this.tools;\n }\n\n override async cleanup(): Promise<void> {\n this.tools = [];\n if (this.context?.logger) {\n this.context.logger.info('HCS-2 Plugin cleaned up');\n }\n }\n}","import {\n GenericPluginContext,\n HederaTool,\n BasePlugin,\n HederaAgentKit,\n} from 'hedera-agent-kit';\nimport {\n InscriberBuilder,\n InscribeFromUrlTool,\n InscribeFromFileTool,\n InscribeFromBufferTool,\n InscribeHashinalTool,\n RetrieveInscriptionTool,\n} from '@hashgraphonline/standards-agent-kit';\n\n/**\n * Plugin providing content inscription tools for Hedera\n */\nexport class InscribePlugin extends BasePlugin {\n id = 'inscribe';\n name = 'Inscribe Plugin';\n description =\n 'Content inscription tools for storing data on Hedera Consensus Service';\n version = '1.0.0';\n author = 'Hashgraph Online';\n namespace = 'inscribe';\n\n private tools: HederaTool[] = [];\n\n override async initialize(context: GenericPluginContext): Promise<void> {\n await super.initialize(context);\n\n const hederaKit = context.config.hederaKit as HederaAgentKit;\n if (!hederaKit) {\n this.context.logger.warn(\n 'HederaKit not found in context. Inscription tools will not be available.'\n );\n return;\n }\n\n try {\n this.initializeTools();\n\n this.context.logger.info(\n 'Inscribe Plugin initialized successfully'\n );\n } catch (error) {\n this.context.logger.error(\n 'Failed to initialize Inscribe plugin:',\n error\n );\n }\n }\n\n private initializeTools(): void {\n const hederaKit = this.context.config.hederaKit as HederaAgentKit;\n if (!hederaKit) {\n throw new Error('HederaKit not found in context config');\n }\n\n const inscriberBuilder = new InscriberBuilder(hederaKit);\n\n this.tools = [\n new InscribeFromUrlTool({\n hederaKit: hederaKit,\n inscriberBuilder: inscriberBuilder,\n logger: this.context.logger,\n }),\n new InscribeFromFileTool({\n hederaKit: hederaKit,\n inscriberBuilder: inscriberBuilder,\n logger: this.context.logger,\n }),\n new InscribeFromBufferTool({\n hederaKit: hederaKit,\n inscriberBuilder: inscriberBuilder,\n logger: this.context.logger,\n }),\n new InscribeHashinalTool({\n hederaKit: hederaKit,\n inscriberBuilder: inscriberBuilder,\n logger: this.context.logger,\n }),\n new RetrieveInscriptionTool({\n hederaKit: hederaKit,\n inscriberBuilder: inscriberBuilder,\n logger: this.context.logger,\n }),\n ];\n }\n\n getTools(): HederaTool[] {\n return this.tools;\n }\n\n override async cleanup(): Promise<void> {\n this.tools = [];\n if (this.context?.logger) {\n this.context.logger.info('Inscribe Plugin cleaned up');\n }\n }\n}","import {\n AccountId,\n Hbar,\n TransferTransaction,\n} from '@hashgraph/sdk';\nimport BigNumber from 'bignumber.js';\nimport { HederaAgentKit, BaseServiceBuilder } from 'hedera-agent-kit';\nimport { HbarTransferParams } from './types';\n\n/**\n * Custom AccountBuilder that properly handles HBAR decimal conversion\n */\nexport class AccountBuilder extends BaseServiceBuilder {\n constructor(hederaKit: HederaAgentKit) {\n super(hederaKit);\n }\n\n /**\n * Transfers HBAR between accounts with proper decimal handling\n */\n public transferHbar(\n params: HbarTransferParams,\n isUserInitiated: boolean = true\n ): this {\n this.clearNotes();\n const transaction = new TransferTransaction();\n \n if (!params.transfers || params.transfers.length === 0) {\n throw new Error('HbarTransferParams must include at least one transfer.');\n }\n\n let netZeroInTinybars = new BigNumber(0);\n let userTransferProcessedForScheduling = false;\n\n if (\n isUserInitiated &&\n this.kit.userAccountId &&\n (this.kit.operationalMode as string) === 'provideBytes' &&\n params.transfers.length === 1\n ) {\n const receiverTransfer = params.transfers[0];\n const amountValue =\n typeof receiverTransfer.amount === 'string' ||\n typeof receiverTransfer.amount === 'number'\n ? receiverTransfer.amount\n : receiverTransfer.amount.toString();\n\n const amountBigNum = new BigNumber(amountValue);\n\n if (amountBigNum.isPositive()) {\n const recipientAccountId =\n typeof receiverTransfer.accountId === 'string'\n ? AccountId.fromString(receiverTransfer.accountId)\n : receiverTransfer.accountId;\n\n const roundedAmount = amountBigNum.toFixed(8, BigNumber.ROUND_DOWN);\n const sdkHbarAmount = Hbar.fromString(roundedAmount);\n\n this.logger.info(\n `[AccountBuilder.transferHbar] Configuring user-initiated scheduled transfer: ${sdkHbarAmount.toString()} from ${\n this.kit.userAccountId\n } to ${recipientAccountId.toString()}`\n );\n \n this.addNote(\n `Configured HBAR transfer from your account (${\n this.kit.userAccountId\n }) to ${recipientAccountId.toString()} for ${sdkHbarAmount.toString()}.`\n );\n\n transaction.addHbarTransfer(recipientAccountId, sdkHbarAmount);\n transaction.addHbarTransfer(\n AccountId.fromString(this.kit.userAccountId),\n sdkHbarAmount.negated()\n );\n\n userTransferProcessedForScheduling = true;\n }\n }\n\n if (!userTransferProcessedForScheduling) {\n const processedTransfers: Array<{\n accountId: AccountId;\n amount: BigNumber;\n hbar: Hbar;\n }> = [];\n \n for (const transferInput of params.transfers) {\n const accountId =\n typeof transferInput.accountId === 'string'\n ? AccountId.fromString(transferInput.accountId)\n : transferInput.accountId;\n\n const amountValue =\n typeof transferInput.amount === 'string' ||\n typeof transferInput.amount === 'number'\n ? transferInput.amount\n : transferInput.amount.toString();\n\n const amountBigNum = new BigNumber(amountValue);\n const roundedAmount = amountBigNum.toFixed(8, BigNumber.ROUND_DOWN);\n \n this.logger.info(\n `Processing transfer: ${amountValue} HBAR (rounded to ${roundedAmount}) for account ${accountId.toString()}`\n );\n\n const sdkHbarAmount = Hbar.fromString(roundedAmount);\n processedTransfers.push({\n accountId,\n amount: amountBigNum,\n hbar: sdkHbarAmount\n });\n\n const tinybarsContribution = sdkHbarAmount.toTinybars();\n netZeroInTinybars = netZeroInTinybars.plus(\n tinybarsContribution.toString()\n );\n }\n\n if (!netZeroInTinybars.isZero()) {\n this.logger.warn(\n `Transfer sum not zero: ${netZeroInTinybars.toString()} tinybars off. Adjusting last transfer.`\n );\n \n if (processedTransfers.length > 0) {\n const lastTransfer = processedTransfers[processedTransfers.length - 1];\n const adjustment = netZeroInTinybars.dividedBy(-100000000);\n const adjustedAmount = lastTransfer.amount.plus(adjustment);\n const adjustedRounded = adjustedAmount.toFixed(8, BigNumber.ROUND_DOWN);\n lastTransfer.hbar = Hbar.fromString(adjustedRounded);\n \n this.logger.info(\n `Adjusted last transfer for ${lastTransfer.accountId.toString()} to ${adjustedRounded} HBAR`\n );\n }\n }\n \n for (const transfer of processedTransfers) {\n transaction.addHbarTransfer(transfer.accountId, transfer.hbar);\n }\n }\n\n if (typeof params.memo !== 'undefined') {\n if (params.memo === null) {\n this.logger.warn('Received null for memo in transferHbar.');\n } else {\n transaction.setTransactionMemo(params.memo);\n }\n }\n\n this.setCurrentTransaction(transaction);\n return this;\n }\n}","import { z } from 'zod';\nimport { HbarTransferParams } from './types';\nimport { AccountBuilder } from './AccountBuilder';\nimport { BaseHederaTransactionTool, BaseServiceBuilder } from 'hedera-agent-kit';\n\nconst HbarTransferInputSchema = z.object({\n accountId: z\n .string()\n .describe('Account ID for the transfer (e.g., \"0.0.xxxx\").'),\n amount: z\n .union([z.number(), z.string()])\n .describe(\n 'HBAR amount in decimal format (e.g., 1 for 1 HBAR, 0.5 for 0.5 HBAR). Positive for credit, negative for debit. DO NOT multiply by 10^8 for tinybars - just use the HBAR amount directly.'\n ),\n});\n\nconst TransferHbarZodSchemaCore = z.object({\n transfers: z\n .array(HbarTransferInputSchema)\n .min(1)\n .describe(\n 'Array of transfers. For simple transfers from your operator account, just include the recipient with positive amount: [{accountId: \"0.0.800\", amount: 1}]. For complex multi-party transfers, include all parties with negative amounts for senders and positive for receivers.'\n ),\n memo: z.string().optional().describe('Optional. Memo for the transaction.'),\n});\n\n/**\n * A Hedera transaction tool for transferring HBAR between accounts.\n * Supports single and multi-party transfers with automatic balance validation.\n * Extends BaseHederaTransactionTool to handle HBAR transfer transactions on the Hedera Hashgraph.\n */\nexport class TransferHbarTool extends BaseHederaTransactionTool<\n typeof TransferHbarZodSchemaCore\n> {\n name = 'hedera-account-transfer-hbar-v2';\n description =\n 'PRIMARY TOOL FOR HBAR TRANSFERS: Transfers HBAR between accounts. For simple transfers from the operator account, just specify the recipient with a positive amount (e.g., [{accountId: \"0.0.800\", amount: 1}] to send 1 HBAR to 0.0.800). The sender will be automatically added. For multi-party transfers (e.g., \"A sends 5 HBAR to C and B sends 3 HBAR to C\"), include ALL transfers with their amounts (negative for senders, positive for receivers).';\n specificInputSchema = TransferHbarZodSchemaCore;\n namespace = 'account';\n\n\n /**\n * Creates and returns the service builder for account operations.\n * \n * @returns BaseServiceBuilder instance configured for account operations\n */\n protected getServiceBuilder(): BaseServiceBuilder {\n return new AccountBuilder(this.hederaKit) as BaseServiceBuilder;\n }\n\n /**\n * Executes the HBAR transfer using the provided builder and arguments.\n * Validates that all transfers sum to zero before execution.\n * \n * @param builder - The service builder instance for executing transactions\n * @param specificArgs - The validated transfer parameters including transfers array and optional memo\n * @returns Promise that resolves when the transfer is complete\n */\n protected async callBuilderMethod(\n builder: BaseServiceBuilder,\n specificArgs: z.infer<typeof TransferHbarZodSchemaCore>\n ): Promise<void> {\n await (builder as AccountBuilder).transferHbar(\n specificArgs as unknown as HbarTransferParams\n );\n }\n}","import { StructuredTool } from '@langchain/core/tools';\nimport { z } from 'zod';\nimport { HederaAgentKit } from 'hedera-agent-kit';\nimport { Logger } from '@hashgraphonline/standards-sdk';\n\ninterface TokenInfo {\n decimals: number;\n [key: string]: unknown;\n}\n\ninterface ToolWithCall {\n _call(input: unknown): Promise<string>;\n}\n\ninterface AgentKitWithMirrorNode {\n mirrorNode?: {\n getTokenInfo(tokenId: string): Promise<TokenInfo>;\n };\n network: string;\n}\n\nexport class AirdropToolWrapper extends StructuredTool {\n name = 'hedera-hts-airdrop-token';\n description =\n 'Airdrops fungible tokens to multiple recipients. Automatically converts human-readable amounts to smallest units based on token decimals.';\n\n schema = z.object({\n tokenId: z\n .string()\n .describe('The ID of the fungible token to airdrop (e.g., \"0.0.yyyy\").'),\n recipients: z\n .array(\n z.object({\n accountId: z\n .string()\n .describe('Recipient account ID (e.g., \"0.0.xxxx\").'),\n amount: z\n .union([z.number(), z.string()])\n .describe(\n 'Amount in human-readable format (e.g., \"10\" for 10 tokens).'\n ),\n })\n )\n .min(1)\n .describe('Array of recipient objects, each with accountId and amount.'),\n memo: z.string().optional().describe('Optional. Memo for the transaction.'),\n });\n\n private originalTool: StructuredTool & ToolWithCall;\n private agentKit: HederaAgentKit & AgentKitWithMirrorNode;\n private logger: Logger;\n\n constructor(originalTool: StructuredTool, agentKit: unknown) {\n super();\n this.originalTool = originalTool as StructuredTool & ToolWithCall;\n this.agentKit = agentKit as HederaAgentKit & AgentKitWithMirrorNode;\n this.logger = new Logger({ module: 'AirdropToolWrapper' });\n }\n\n async _call(input: z.infer<typeof this.schema>): Promise<string> {\n try {\n this.logger.info(\n `Processing airdrop request for token ${input.tokenId} with ${input.recipients.length} recipients`\n );\n\n const tokenInfo = await this.getTokenInfo(input.tokenId);\n const decimals = tokenInfo.decimals || 0;\n\n this.logger.info(`Token ${input.tokenId} has ${decimals} decimal places`);\n\n const convertedRecipients = input.recipients.map((recipient) => {\n const humanAmount =\n typeof recipient.amount === 'string'\n ? parseFloat(recipient.amount)\n : recipient.amount;\n const smallestUnitAmount = this.convertToSmallestUnits(\n humanAmount,\n decimals\n );\n\n this.logger.info(\n `Converting amount for ${recipient.accountId}: ${humanAmount} tokens → ${smallestUnitAmount} smallest units`\n );\n\n return {\n ...recipient,\n amount: smallestUnitAmount.toString(),\n };\n });\n\n const convertedInput = {\n ...input,\n recipients: convertedRecipients,\n };\n\n this.logger.info(`Calling original airdrop tool with converted amounts`);\n return await this.originalTool._call(convertedInput);\n } catch (error) {\n this.logger.error('Error in airdrop tool wrapper:', error);\n throw error;\n }\n }\n\n private convertToSmallestUnits(amount: number, decimals: number): number {\n return Math.floor(amount * Math.pow(10, decimals));\n }\n\n private async getTokenInfo(tokenId: string): Promise<TokenInfo> {\n return await this.queryTokenInfo(tokenId);\n }\n\n private async queryTokenInfo(tokenId: string): Promise<TokenInfo> {\n try {\n this.logger.info('Querying token info using mirror node');\n const mirrorNode = this.agentKit.mirrorNode;\n if (!mirrorNode) {\n this.logger.info(\n 'MirrorNode not found in agentKit, attempting to access via fetch'\n );\n const network = this.agentKit.network || 'testnet';\n const mirrorNodeUrl =\n network === 'mainnet'\n ? 'https://mainnet.mirrornode.hedera.com'\n : 'https://testnet.mirrornode.hedera.com';\n\n const response = await fetch(\n `${mirrorNodeUrl}/api/v1/tokens/${tokenId}`\n );\n if (response.ok) {\n const tokenData = (await response.json()) as Record<string, unknown>;\n const decimals = parseInt(String(tokenData.decimals || '0'));\n this.logger.info(\n `Token ${tokenId} found with ${decimals} decimals via API`\n );\n return { ...tokenData, decimals };\n }\n } else {\n const tokenData = await mirrorNode.getTokenInfo(tokenId);\n\n if (tokenData && typeof tokenData.decimals !== 'undefined') {\n const decimals = parseInt(tokenData.decimals.toString()) || 0;\n this.logger.info(`Token ${tokenId} found with ${decimals} decimals`);\n return { ...tokenData, decimals };\n }\n }\n\n throw new Error(`Token data not found or missing decimals field`);\n } catch (error) {\n this.logger.warn(`Failed to query token info for ${tokenId}:`, error);\n\n this.logger.info(\n 'Falling back to assumed 0 decimal places (smallest units)'\n );\n return { decimals: 0 };\n }\n }\n}\n","import {\n GenericPluginContext,\n HederaTool,\n BasePlugin,\n HederaAgentKit,\n HederaAirdropTokenTool,\n} from 'hedera-agent-kit';\nimport { TransferHbarTool } from './TransferHbarTool';\nimport { AirdropToolWrapper } from './AirdropToolWrapper';\nimport { StructuredTool } from '@langchain/core/tools';\n\nexport class HbarPlugin extends BasePlugin {\n id = 'hbar';\n name = 'HBAR Plugin';\n description =\n 'HBAR operations: transfer tool with robust decimal handling and compatibility with airdrop improvements';\n version = '1.0.0';\n author = 'Hashgraph Online';\n namespace = 'account';\n\n private tools: (HederaTool | AirdropToolWrapper)[] = [];\n private originalAirdropTool: StructuredTool | null = null;\n\n override async initialize(context: GenericPluginContext): Promise<void> {\n await super.initialize(context);\n\n const hederaKit = context.config.hederaKit as HederaAgentKit;\n if (!hederaKit) {\n this.context.logger.warn(\n 'HederaKit not found in context. HBAR tools will not be available.'\n );\n return;\n }\n\n try {\n this.initializeTools();\n\n this.context.logger.info('HBAR Plugin initialized successfully');\n } catch (error) {\n this.context.logger.error('Failed to initialize HBAR plugin:', error);\n }\n }\n\n private initializeTools(): void {\n const hederaKit = this.context.config.hederaKit as HederaAgentKit;\n if (!hederaKit) {\n throw new Error('HederaKit not found in context config');\n }\n\n const transfer = new TransferHbarTool({\n hederaKit: hederaKit,\n logger: this.context.logger,\n });\n\n this.tools = [transfer];\n\n try {\n this.context.logger.info(\n 'Creating wrapper for passed original airdrop tool'\n );\n\n const airdropTool = new HederaAirdropTokenTool({\n hederaKit: hederaKit,\n logger: this.context.logger,\n });\n const wrappedAirdropTool = new AirdropToolWrapper(airdropTool, hederaKit);\n this.tools.push(wrappedAirdropTool);\n this.context.logger.info('Added wrapped airdrop tool to HBAR Plugin');\n } catch (error) {\n this.context.logger.error('Error creating airdrop tool wrapper:', error);\n }\n\n this.context.logger.info(\n `HBAR Plugin tools initialized with ${this.tools.length} tools`\n );\n }\n\n override getTools(): HederaTool[] {\n // @ts-ignore\n return this.tools;\n }\n\n async shutdown(): Promise<void> {\n this.tools = [];\n }\n}\n","import { AgentExecutor } from 'langchain/agents';\nimport { Logger } from '@hashgraphonline/standards-sdk';\n\n/**\n * Custom AgentExecutor that intercepts large tool outputs and converts them to content references\n * before they are sent to the LLM to avoid token limit issues.\n * \n * Note: The content reference conversion is already handled in the MCP adapter,\n * so this class currently just extends AgentExecutor without modifications.\n * We keep it as a placeholder for future enhancements.\n */\nexport class ContentAwareAgentExecutor extends AgentExecutor {\n private logger: Logger;\n\n constructor(config: any) {\n super(config);\n this.logger = new Logger({ module: 'ContentAwareAgentExecutor' });\n }\n}","import type { BaseMessage } from '@langchain/core/messages';\nimport type { StructuredTool } from '@langchain/core/tools';\nimport type { TransactionReceipt } from '@hashgraph/sdk';\nimport {\n HederaAgentKit,\n ServerSigner,\n TokenUsageCallbackHandler,\n TokenUsage,\n BasePlugin,\n} from 'hedera-agent-kit';\nimport type { CostCalculation } from 'hedera-agent-kit';\nimport type { AIProvider, VercelAIProvider, BAMLProvider } from './providers';\nimport { Logger } from '@hashgraphonline/standards-sdk';\nimport type { MCPServerConfig, MCPConnectionStatus } from './mcp/types';\n\nexport interface ToolFilterConfig {\n namespaceWhitelist?: string[];\n toolBlacklist?: string[];\n toolPredicate?: (tool: StructuredTool) => boolean;\n}\n\nexport type ExecutionMode = 'direct' | 'bytes';\nexport type OperationalMode = 'autonomous' | 'returnBytes';\n\nexport interface HederaAgentConfiguration {\n signer: ServerSigner;\n execution?: {\n mode?: ExecutionMode;\n operationalMode?: OperationalMode;\n userAccountId?: string;\n scheduleUserTransactions?: boolean;\n scheduleUserTransactionsInBytesMode?: boolean;\n };\n ai?: {\n provider?: AIProvider;\n llm?: unknown;\n apiKey?: string;\n modelName?: string;\n temperature?: number;\n };\n filtering?: ToolFilterConfig;\n messaging?: {\n systemPreamble?: string;\n systemPostamble?: string;\n conciseMode?: boolean;\n };\n extensions?: {\n plugins?: BasePlugin[];\n mirrorConfig?: Record<string, unknown>;\n modelCapability?: string;\n };\n mcp?: {\n servers?: MCPServerConfig[];\n autoConnect?: boolean;\n };\n debug?: {\n verbose?: boolean;\n silent?: boolean;\n };\n}\n\nexport interface ConversationContext {\n messages: BaseMessage[];\n metadata?: Record<string, unknown>;\n}\n\nexport interface ChatResponse {\n output: string;\n message?: string;\n transactionBytes?: string;\n receipt?: TransactionReceipt | object;\n scheduleId?: string;\n transactionId?: string;\n notes?: string[];\n error?: string;\n intermediateSteps?: unknown;\n rawToolOutput?: unknown;\n tokenUsage?: TokenUsage;\n cost?: CostCalculation;\n metadata?: Record<string, unknown>;\n tool_calls?: Array<{\n id: string;\n name: string;\n args: Record<string, unknown>;\n output?: string;\n }>;\n [key: string]: unknown;\n}\n\nexport interface UsageStats extends TokenUsage {\n cost: CostCalculation;\n}\n\nexport abstract class BaseAgent {\n protected logger: Logger;\n protected agentKit: HederaAgentKit | undefined;\n protected tools: StructuredTool[] = [];\n protected initialized = false;\n protected tokenTracker: TokenUsageCallbackHandler | undefined;\n\n constructor(protected config: HederaAgentConfiguration) {\n this.logger = new Logger({\n module: 'BaseAgent',\n silent: config.debug?.silent || false,\n });\n }\n\n abstract boot(): Promise<void>;\n abstract chat(\n message: string,\n context?: ConversationContext\n ): Promise<ChatResponse>;\n abstract shutdown(): Promise<void>;\n abstract switchMode(mode: OperationalMode): void;\n abstract getUsageStats(): UsageStats;\n abstract getUsageLog(): UsageStats[];\n abstract clearUsageStats(): void;\n abstract connectMCPServers(): Promise<void>;\n abstract getMCPConnectionStatus(): Map<string, MCPConnectionStatus>;\n\n public getCore(): HederaAgentKit | undefined {\n return this.agentKit;\n }\n\n protected filterTools(tools: StructuredTool[]): StructuredTool[] {\n let filtered = [...tools];\n const filter = this.config.filtering;\n\n if (!filter) return filtered;\n\n if (filter.namespaceWhitelist?.length) {\n filtered = filtered.filter((tool) => {\n const namespace = (tool as StructuredTool & { namespace?: string })\n .namespace;\n return !namespace || filter.namespaceWhitelist!.includes(namespace);\n });\n }\n\n if (filter.toolBlacklist?.length) {\n filtered = filtered.filter(\n (tool) => !filter.toolBlacklist!.includes(tool.name)\n );\n }\n\n if (filter.toolPredicate) {\n filtered = filtered.filter(filter.toolPredicate);\n }\n\n this.logger.debug(`Filtered tools: ${tools.length} → ${filtered.length}`);\n return filtered;\n }\n\n protected buildSystemPrompt(): string {\n const parts: string[] = [];\n const operatorId = this.config.signer.getAccountId().toString();\n const userAccId = this.config.execution?.userAccountId;\n\n if (this.config.messaging?.systemPreamble) {\n parts.push(this.config.messaging.systemPreamble);\n }\n\n parts.push(\n `You are a helpful Hedera assistant. Your primary operator account is ${operatorId}. ` +\n `You have tools to interact with the Hedera Hashgraph. ` +\n `When using any tool, provide all necessary parameters as defined by that tool's schema and description.`\n );\n\n if (userAccId) {\n parts.push(\n `The user you are assisting has a personal Hedera account ID: ${userAccId}. ` +\n `IMPORTANT: When the user says things like \"I want to send HBAR\" or \"transfer my tokens\", you MUST use ${userAccId} as the sender/from account. ` +\n `For example, if user says \"I want to send 2 HBAR to 0.0.800\", you must set up a transfer where ${userAccId} sends the HBAR, not your operator account.`\n );\n }\n\n const operationalMode =\n this.config.execution?.operationalMode || 'returnBytes';\n if (operationalMode === 'autonomous') {\n parts.push(\n `\\nOPERATIONAL MODE: 'autonomous'. Your goal is to execute transactions directly using your tools. ` +\n `Your account ${operatorId} will be the payer for these transactions. ` +\n `Even if the user's account (${\n userAccId || 'a specified account'\n }) is the actor in the transaction body (e.g., sender of HBAR), ` +\n `you (the agent with operator ${operatorId}) are still executing and paying. For HBAR transfers, ensure the amounts in the 'transfers' array sum to zero (as per tool schema), balancing with your operator account if necessary.`\n );\n } else {\n if (\n this.config.execution?.scheduleUserTransactionsInBytesMode &&\n userAccId\n ) {\n parts.push(\n `\\nOPERATIONAL MODE: 'returnBytes' with scheduled transactions for user actions. ` +\n `When a user asks for a transaction to be prepared (e.g., creating a token, topic, transferring assets for them to sign, etc), ` +\n `you MUST default to creating a Scheduled Transaction using the appropriate tool with the metaOption 'schedule: true'. ` +\n `The user (with account ID ${userAccId}) will be the one to ultimately pay for and (if needed) sign the inner transaction. ` +\n `Your operator account (${operatorId}) will pay for creating the schedule entity itself. ` +\n `You MUST return the ScheduleId and details of the scheduled operation in a structured JSON format with these fields: success, op, schedule_id, description, payer_account_id_scheduled_tx, and scheduled_transaction_details.`\n );\n } else {\n parts.push(\n `\\nOPERATIONAL MODE: 'returnBytes'. Your goal is to provide transaction bytes when possible. ` +\n `When a user asks for a transaction to be prepared (e.g., for them to sign, or for scheduling without the default scheduling flow), ` +\n `you MUST call the appropriate tool. ` +\n `IMPORTANT: Only use metaOption 'returnBytes: true' for tools that explicitly support it (like HBAR transfers, token operations). ` +\n `Many tools (inscriptions, HCS-2, HCS-20, etc.) do NOT support returnBytes and will execute directly - this is expected behavior. ` +\n `For tools without returnBytes support, simply call them with their standard parameters. ` +\n `If you need raw bytes for the user to sign for their own account ${\n userAccId || 'if specified'\n }, ensure the tool constructs the transaction body accordingly when returnBytes IS supported.`\n );\n }\n }\n\n if (this.config.messaging?.conciseMode !== false) {\n parts.push(\n '\\nAlways be concise. If the tool provides a JSON string as its primary output (especially in returnBytes mode), make your accompanying text brief. If the tool does not provide JSON output or an error occurs, your narrative becomes primary; if notes were generated by the tool in such cases, append them to your textual response.'\n );\n }\n\n if (this.config.messaging?.systemPostamble) {\n parts.push(this.config.messaging.systemPostamble);\n }\n\n return parts.join('\\n');\n }\n\n isReady(): boolean {\n return this.initialized;\n }\n}\n\nexport type { AIProvider, VercelAIProvider, BAMLProvider };\n","import type { ContentType, ContentSource } from '../types/content-reference';\nimport type { ContentStorage } from '../memory/ContentStorage';\nimport { Logger } from '@hashgraphonline/standards-sdk';\n\nexport interface MCPResponseContent {\n content: unknown;\n type: 'text' | 'image' | 'resource' | 'text[]' | 'image[]';\n sizeBytes: number;\n mimeType?: string;\n}\n\nexport interface ProcessedResponse {\n content: unknown;\n wasProcessed: boolean;\n referenceCreated?: boolean;\n referenceId?: string;\n originalSize?: number;\n errors?: string[];\n}\n\nexport interface ContentAnalysis {\n shouldProcess: boolean;\n contents: MCPResponseContent[];\n totalSize: number;\n largestContentSize: number;\n}\n\nexport class MCPContentProcessor {\n private contentStorage: ContentStorage;\n private logger: Logger;\n\n constructor(contentStorage: ContentStorage, logger: Logger) {\n this.contentStorage = contentStorage;\n this.logger = logger;\n }\n\n analyzeResponse(response: unknown): ContentAnalysis {\n const contents: MCPResponseContent[] = [];\n let totalSize = 0;\n\n this.extractContentFromResponse(response, contents);\n\n totalSize = contents.reduce((sum, content) => sum + content.sizeBytes, 0);\n const largestContentSize = contents.reduce((max, content) => \n Math.max(max, content.sizeBytes), 0);\n\n const shouldProcess = contents.some(content => \n this.contentStorage.shouldUseReference(\n typeof content.content === 'string' \n ? content.content \n : JSON.stringify(content.content)\n )\n );\n\n return {\n shouldProcess,\n contents,\n totalSize,\n largestContentSize\n };\n }\n\n async processResponse(\n response: unknown,\n serverName: string,\n toolName: string\n ): Promise<ProcessedResponse> {\n try {\n const analysis = this.analyzeResponse(response);\n \n if (!analysis.shouldProcess) {\n return {\n content: response,\n wasProcessed: false\n };\n }\n\n const processedResponse = await this.createReferencedResponse(\n response,\n analysis,\n serverName,\n toolName\n );\n\n return processedResponse;\n } catch (error) {\n this.logger.error('Error processing MCP response:', error);\n return {\n content: response,\n wasProcessed: false,\n errors: [error instanceof Error ? error.message : 'Unknown processing error']\n };\n }\n }\n\n private extractContentFromResponse(obj: unknown, contents: MCPResponseContent[]): void {\n if (obj === null || obj === undefined) {\n return;\n }\n\n if (Array.isArray(obj)) {\n obj.forEach(item => this.extractContentFromResponse(item, contents));\n return;\n }\n\n if (typeof obj === 'object') {\n const record = obj as Record<string, unknown>;\n \n if (record.type === 'text' && typeof record.text === 'string') {\n contents.push({\n content: record.text,\n type: 'text',\n sizeBytes: Buffer.byteLength(record.text, 'utf8'),\n mimeType: this.detectMimeType(record.text as string)\n });\n return;\n }\n\n if (record.type === 'image' && typeof record.data === 'string') {\n contents.push({\n content: record.data,\n type: 'image',\n sizeBytes: Math.ceil(record.data.length * 0.75),\n mimeType: record.mimeType as string || 'image/jpeg'\n });\n return;\n }\n\n if (record.type === 'resource' && record.resource) {\n const resourceStr = JSON.stringify(record.resource);\n contents.push({\n content: resourceStr,\n type: 'resource',\n sizeBytes: Buffer.byteLength(resourceStr, 'utf8'),\n mimeType: 'application/json'\n });\n return;\n }\n\n Object.values(record).forEach(value => \n this.extractContentFromResponse(value, contents));\n return;\n }\n\n if (typeof obj === 'string') {\n if (obj.length > 1000) {\n contents.push({\n content: obj,\n type: 'text',\n sizeBytes: Buffer.byteLength(obj, 'utf8'),\n mimeType: this.detectMimeType(obj)\n });\n }\n }\n }\n\n private async createReferencedResponse(\n originalResponse: unknown,\n analysis: ContentAnalysis,\n serverName: string,\n toolName: string\n ): Promise<ProcessedResponse> {\n const processedResponse = this.deepClone(originalResponse);\n const errors: string[] = [];\n let referenceCreated = false;\n let totalReferenceSize = 0;\n\n for (const contentInfo of analysis.contents) {\n if (this.contentStorage.shouldUseReference(\n typeof contentInfo.content === 'string' \n ? contentInfo.content \n : JSON.stringify(contentInfo.content)\n )) {\n try {\n const contentBuffer = Buffer.from(\n typeof contentInfo.content === 'string' \n ? contentInfo.content \n : JSON.stringify(contentInfo.content),\n 'utf8'\n );\n\n const contentType = this.mapMimeTypeToContentType(contentInfo.mimeType);\n \n const metadata: Parameters<typeof this.contentStorage.storeContentIfLarge>[1] = {\n contentType,\n source: 'mcp_tool' as ContentSource,\n mcpToolName: `${serverName}::${toolName}`,\n tags: ['mcp_response', serverName, toolName]\n };\n \n if (contentInfo.mimeType !== undefined) {\n metadata.mimeType = contentInfo.mimeType;\n }\n \n const reference = await this.contentStorage.storeContentIfLarge(\n contentBuffer,\n metadata\n );\n\n if (reference) {\n this.replaceContentInResponse(\n processedResponse,\n contentInfo.content,\n this.createLightweightReference(reference)\n );\n referenceCreated = true;\n totalReferenceSize += contentBuffer.length;\n }\n } catch (error) {\n errors.push(`Failed to create reference: ${error instanceof Error ? error.message : 'Unknown error'}`);\n }\n }\n }\n\n const result: ProcessedResponse = {\n content: processedResponse,\n wasProcessed: true,\n referenceCreated,\n originalSize: totalReferenceSize\n };\n \n if (errors.length > 0) {\n result.errors = errors;\n }\n \n return result;\n }\n\n private createLightweightReference(reference: any): Record<string, unknown> {\n return {\n type: 'content_reference',\n referenceId: reference.referenceId,\n preview: reference.preview,\n size: reference.metadata.sizeBytes,\n contentType: reference.metadata.contentType,\n format: 'ref://{id}',\n _isReference: true\n };\n }\n\n private replaceContentInResponse(obj: unknown, oldContent: unknown, newContent: any): void {\n if (obj === null || obj === undefined) {\n return;\n }\n\n if (Array.isArray(obj)) {\n for (let i = 0; i < obj.length; i++) {\n if (obj[i] === oldContent) {\n obj[i] = newContent;\n } else {\n this.replaceContentInResponse(obj[i], oldContent, newContent);\n }\n }\n return;\n }\n\n if (typeof obj === 'object') {\n const record = obj as Record<string, unknown>;\n if (record.type === 'text' && record.text === oldContent) {\n for (const key of Object.keys(record)) {\n delete record[key];\n }\n for (const key of Object.keys(newContent)) {\n record[key] = newContent[key];\n }\n return;\n }\n for (const key in record) {\n if (record[key] === oldContent) {\n record[key] = newContent;\n } else {\n this.replaceContentInResponse(record[key], oldContent, newContent);\n }\n }\n }\n }\n\n private detectMimeType(content: string): string {\n if (content.trim().startsWith('{') || content.trim().startsWith('[')) {\n return 'application/json';\n }\n if (content.includes('<html>') || content.includes('<!DOCTYPE')) {\n return 'text/html';\n }\n if (content.includes('# ') || content.includes('## ')) {\n return 'text/markdown';\n }\n return 'text/plain';\n }\n\n private mapMimeTypeToContentType(mimeType?: string): ContentType {\n if (!mimeType) return 'text';\n \n if (mimeType.startsWith('text/plain')) return 'text';\n if (mimeType === 'application/json') return 'json';\n if (mimeType === 'text/html') return 'html';\n if (mimeType === 'text/markdown') return 'markdown';\n if (mimeType.startsWith('text/')) return 'text';\n \n return 'binary';\n }\n\n private deepClone<T>(obj: T): T {\n if (obj === null || typeof obj !== 'object') {\n return obj;\n }\n \n if (obj instanceof Date) {\n return new Date(obj.getTime()) as T;\n }\n \n if (Array.isArray(obj)) {\n return obj.map(item => this.deepClone(item)) as T;\n }\n \n const cloned = {} as T;\n for (const key in obj) {\n if (obj.hasOwnProperty(key)) {\n cloned[key] = this.deepClone(obj[key]);\n }\n }\n \n return cloned;\n }\n}","import { Client } from '@modelcontextprotocol/sdk/client/index.js';\nimport { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';\nimport type { MCPServerConfig, MCPToolInfo, MCPConnectionStatus } from './types';\nimport { Logger } from '@hashgraphonline/standards-sdk';\nimport type { ContentStorage } from '../memory/ContentStorage';\nimport { MCPContentProcessor, ProcessedResponse } from './ContentProcessor';\n\n/**\n * Manages connections to MCP servers and tool discovery\n */\nexport class MCPClientManager {\n private clients: Map<string, Client> = new Map();\n private tools: Map<string, MCPToolInfo[]> = new Map();\n private logger: Logger;\n private contentProcessor?: MCPContentProcessor;\n\n constructor(logger: Logger, contentStorage?: ContentStorage) {\n this.logger = logger;\n if (contentStorage) {\n this.contentProcessor = new MCPContentProcessor(contentStorage, logger);\n }\n }\n\n /**\n * Connect to an MCP server and discover its tools\n */\n async connectServer(config: MCPServerConfig): Promise<MCPConnectionStatus> {\n try {\n if (this.isServerConnected(config.name)) {\n return {\n serverName: config.name,\n connected: false,\n error: `Server ${config.name} is already connected`,\n tools: [],\n };\n }\n\n if (config.transport && config.transport !== 'stdio') {\n throw new Error(`Transport ${config.transport} not yet supported`);\n }\n\n const transport = new StdioClientTransport({\n command: config.command,\n args: config.args,\n ...(config.env && { env: config.env }),\n });\n\n const client = new Client({\n name: `conversational-agent-${config.name}`,\n version: '1.0.0',\n }, {\n capabilities: {},\n });\n\n await client.connect(transport);\n this.clients.set(config.name, client);\n\n const toolsResponse = await client.listTools();\n const toolsWithServer: MCPToolInfo[] = toolsResponse.tools.map(tool => ({\n ...tool,\n serverName: config.name,\n }));\n\n this.tools.set(config.name, toolsWithServer);\n this.logger.info(`Connected to MCP server ${config.name} with ${toolsWithServer.length} tools`);\n\n return {\n serverName: config.name,\n connected: true,\n tools: toolsWithServer,\n };\n } catch (error) {\n this.logger.error(`Failed to connect to MCP server ${config.name}:`, error);\n return {\n serverName: config.name,\n connected: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n tools: [],\n };\n }\n }\n\n /**\n * Execute a tool on a specific MCP server\n */\n async executeTool(serverName: string, toolName: string, args: Record<string, unknown>): Promise<unknown> {\n const client = this.clients.get(serverName);\n if (!client) {\n throw new Error(`MCP server ${serverName} not connected`);\n }\n\n this.logger.debug(`Executing MCP tool ${toolName} on server ${serverName}`, args);\n\n try {\n const result = await client.callTool({\n name: toolName,\n arguments: args,\n });\n\n if (this.contentProcessor) {\n const processed = await this.contentProcessor.processResponse(result, serverName, toolName);\n \n if (processed.wasProcessed) {\n this.logger.debug(\n `Processed MCP response from ${serverName}::${toolName}`,\n {\n referenceCreated: processed.referenceCreated,\n originalSize: processed.originalSize,\n errors: processed.errors\n }\n );\n\n if (processed.errors && processed.errors.length > 0) {\n this.logger.warn(`Content processing warnings for ${serverName}::${toolName}:`, processed.errors);\n }\n }\n\n return processed.content;\n }\n\n return result;\n } catch (error) {\n this.logger.error(`Error executing MCP tool ${toolName}:`, error);\n throw error;\n }\n }\n\n /**\n * Disconnect all MCP servers\n */\n async disconnectAll(): Promise<void> {\n for (const [name, client] of this.clients) {\n try {\n await client.close();\n this.logger.info(`Disconnected from MCP server ${name}`);\n } catch (error) {\n this.logger.error(`Error disconnecting MCP server ${name}:`, error);\n }\n }\n this.clients.clear();\n this.tools.clear();\n }\n\n /**\n * Get all discovered tools from all connected servers\n */\n getAllTools(): MCPToolInfo[] {\n const allTools: MCPToolInfo[] = [];\n for (const tools of this.tools.values()) {\n allTools.push(...tools);\n }\n return allTools;\n }\n\n /**\n * Get tools from a specific server\n */\n getServerTools(serverName: string): MCPToolInfo[] {\n return this.tools.get(serverName) || [];\n }\n\n /**\n * Check if a server is connected\n */\n isServerConnected(serverName: string): boolean {\n return this.clients.has(serverName);\n }\n\n /**\n * Get list of connected server names\n */\n getConnectedServers(): string[] {\n return Array.from(this.clients.keys());\n }\n\n /**\n * Enable content processing with content storage\n */\n enableContentProcessing(contentStorage: ContentStorage): void {\n this.contentProcessor = new MCPContentProcessor(contentStorage, this.logger);\n this.logger.info('Content processing enabled for MCP responses');\n }\n\n /**\n * Disable content processing\n */\n disableContentProcessing(): void {\n delete this.contentProcessor;\n this.logger.info('Content processing disabled for MCP responses');\n }\n\n /**\n * Check if content processing is enabled\n */\n isContentProcessingEnabled(): boolean {\n return this.contentProcessor !== undefined;\n }\n\n /**\n * Analyze a response without processing it (for testing/debugging)\n */\n analyzeResponseContent(response: unknown): unknown {\n if (!this.contentProcessor) {\n throw new Error('Content processing is not enabled');\n }\n return this.contentProcessor.analyzeResponse(response);\n }\n}","import { DynamicStructuredTool } from '@langchain/core/tools';\nimport { z } from 'zod';\nimport type { MCPToolInfo, MCPServerConfig } from '../types';\nimport type { MCPClientManager } from '../MCPClientManager';\nimport { ContentStoreService, shouldUseReference } from '@hashgraphonline/standards-sdk';\nimport type { ContentSource } from '../../types/content-reference';\n\n/**\n * Convert an MCP tool to a LangChain DynamicStructuredTool\n */\nexport function convertMCPToolToLangChain(\n tool: MCPToolInfo,\n mcpManager: MCPClientManager,\n serverConfig?: MCPServerConfig\n): DynamicStructuredTool {\n const zodSchema = jsonSchemaToZod(tool.inputSchema);\n\n const sanitizedName = `${tool.serverName}_${tool.name}`.replace(\n /[^a-zA-Z0-9_]/g,\n '_'\n );\n\n let description = tool.description || `MCP tool ${tool.name} from ${tool.serverName}`;\n \n if (serverConfig?.toolDescriptions?.[tool.name]) {\n description = `${description}\\n\\n${serverConfig.toolDescriptions[tool.name]}`;\n }\n \n if (serverConfig?.additionalContext) {\n description = `${description}\\n\\nContext: ${serverConfig.additionalContext}`;\n }\n\n return new DynamicStructuredTool({\n name: sanitizedName,\n description,\n schema: zodSchema,\n func: async (input) => {\n try {\n const result = await mcpManager.executeTool(\n tool.serverName,\n tool.name,\n input\n );\n\n let responseText = '';\n \n if (typeof result === 'string') {\n responseText = result;\n } else if (\n result &&\n typeof result === 'object' &&\n 'content' in result\n ) {\n const content = (result as { content: unknown }).content;\n if (Array.isArray(content)) {\n const textParts = content\n .filter(\n (item): item is { type: string; text: string } =>\n typeof item === 'object' &&\n item !== null &&\n 'type' in item &&\n item.type === 'text' &&\n 'text' in item\n )\n .map((item) => item.text);\n responseText = textParts.join('\\n');\n } else {\n responseText = JSON.stringify(content);\n }\n } else {\n responseText = JSON.stringify(result);\n }\n\n const responseBuffer = Buffer.from(responseText, 'utf8');\n \n const MCP_REFERENCE_THRESHOLD = 10 * 1024;\n const shouldStoreMCPContent = responseBuffer.length > MCP_REFERENCE_THRESHOLD;\n \n if (shouldStoreMCPContent || shouldUseReference(responseBuffer)) {\n const contentStore = ContentStoreService.getInstance();\n if (contentStore) {\n try {\n const referenceId = await contentStore.storeContent(responseBuffer, {\n contentType: 'text' as ContentSource,\n source: 'mcp',\n mcpToolName: `${tool.serverName}_${tool.name}`,\n originalSize: responseBuffer.length\n });\n return `content-ref:${referenceId}`;\n } catch (storeError) {\n }\n }\n }\n\n return responseText;\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : 'Unknown error';\n return `Error executing MCP tool ${tool.name}: ${errorMessage}`;\n }\n },\n });\n}\n\n/**\n * Convert JSON Schema to Zod schema\n * This is a simplified converter that handles common cases\n */\nfunction jsonSchemaToZod(schema: unknown): z.ZodTypeAny {\n if (!schema || typeof schema !== 'object') {\n return z.object({});\n }\n\n const schemaObj = schema as Record<string, unknown>;\n\n if (schemaObj.type && schemaObj.type !== 'object') {\n return convertType(schemaObj);\n }\n\n if (!schemaObj.properties || typeof schemaObj.properties !== 'object') {\n return z.object({});\n }\n\n const shape: Record<string, z.ZodTypeAny> = {};\n\n for (const [key, value] of Object.entries(schemaObj.properties)) {\n let zodType = convertType(value);\n\n const isRequired =\n Array.isArray(schemaObj.required) && schemaObj.required.includes(key);\n if (!isRequired) {\n zodType = zodType.optional();\n }\n\n shape[key] = zodType;\n }\n\n return z.object(shape);\n}\n\n/**\n * Convert a single JSON Schema type to Zod\n */\nfunction convertType(schema: unknown): z.ZodTypeAny {\n if (!schema || typeof schema !== 'object' || !('type' in schema)) {\n return z.unknown();\n }\n\n const schemaObj = schema as {\n type: string;\n enum?: unknown[];\n items?: unknown;\n };\n let zodType: z.ZodTypeAny;\n\n switch (schemaObj.type) {\n case 'string':\n zodType = z.string();\n if (schemaObj.enum && Array.isArray(schemaObj.enum)) {\n zodType = z.enum(schemaObj.enum as [string, ...string[]]);\n }\n break;\n\n case 'number':\n zodType = z.number();\n if ('minimum' in schemaObj && typeof schemaObj.minimum === 'number') {\n zodType = (zodType as z.ZodNumber).min(schemaObj.minimum);\n }\n if ('maximum' in schemaObj && typeof schemaObj.maximum === 'number') {\n zodType = (zodType as z.ZodNumber).max(schemaObj.maximum);\n }\n break;\n\n case 'integer':\n zodType = z.number().int();\n if ('minimum' in schemaObj && typeof schemaObj.minimum === 'number') {\n zodType = (zodType as z.ZodNumber).min(schemaObj.minimum);\n }\n if ('maximum' in schemaObj && typeof schemaObj.maximum === 'number') {\n zodType = (zodType as z.ZodNumber).max(schemaObj.maximum);\n }\n break;\n\n case 'boolean':\n zodType = z.boolean();\n break;\n\n case 'array':\n if (schemaObj.items) {\n zodType = z.array(convertType(schemaObj.items));\n } else {\n zodType = z.array(z.unknown());\n }\n break;\n\n case 'object':\n if ('properties' in schemaObj) {\n zodType = jsonSchemaToZod(schemaObj);\n } else {\n zodType = z.object({}).passthrough();\n }\n break;\n\n default:\n zodType = z.unknown();\n }\n\n if ('description' in schemaObj && typeof schemaObj.description === 'string') {\n zodType = zodType.describe(schemaObj.description);\n }\n\n return zodType;\n}\n","import { encoding_for_model } from 'tiktoken';\nimport type { TiktokenModel } from 'tiktoken';\nimport type { BaseMessage } from '@langchain/core/messages';\n\n/**\n * Token counter utility for OpenAI models using tiktoken encoding\n * Provides accurate token counting for text content and chat messages\n */\nexport class TokenCounter {\n private encoding: ReturnType<typeof encoding_for_model>;\n private modelName: string;\n\n private static readonly MESSAGE_OVERHEAD = 3;\n private static readonly ROLE_OVERHEAD = 1;\n\n constructor(modelName: string | TiktokenModel = 'gpt-4o') {\n this.modelName = String(modelName);\n try {\n this.encoding = encoding_for_model(modelName as TiktokenModel);\n } catch {\n this.encoding = encoding_for_model('gpt-4o');\n this.modelName = 'gpt-4o';\n }\n }\n\n /**\n * Count tokens in raw text content\n * @param text - The text to count tokens for\n * @returns Number of tokens\n */\n countTokens(text: string): number {\n if (!text || text.trim() === '') {\n return 0;\n }\n\n try {\n const tokens = this.encoding.encode(text);\n return tokens.length;\n } catch (error) {\n return Math.ceil(text.split(/\\s+/).length * 1.3);\n }\n }\n\n /**\n * Count tokens for a single chat message including role overhead\n * @param message - The message to count tokens for\n * @returns Number of tokens including message formatting overhead\n */\n countMessageTokens(message: BaseMessage): number {\n const contentTokens = this.countTokens(String(message.content ?? ''));\n const roleTokens = this.countTokens(this.getMessageRole(message));\n \n return contentTokens + roleTokens + TokenCounter.MESSAGE_OVERHEAD + TokenCounter.ROLE_OVERHEAD;\n }\n\n /**\n * Count tokens for multiple messages\n * @param messages - Array of messages to count\n * @returns Total token count for all messages\n */\n countMessagesTokens(messages: BaseMessage[]): number {\n if (!messages || messages.length === 0) {\n return 0;\n }\n\n let total = 0;\n for (const message of messages) {\n total += this.countMessageTokens(message);\n }\n return total;\n }\n\n /**\n * Estimate tokens for system prompt\n * System prompts have slightly different overhead in chat completions\n * @param systemPrompt - The system prompt text\n * @returns Estimated token count\n */\n estimateSystemPromptTokens(systemPrompt: string): number {\n if (!systemPrompt || systemPrompt.trim() === '') {\n return 0;\n }\n\n const contentTokens = this.countTokens(systemPrompt);\n const roleTokens = this.countTokens('system');\n \n return contentTokens + roleTokens + TokenCounter.MESSAGE_OVERHEAD + TokenCounter.ROLE_OVERHEAD;\n }\n\n /**\n * Get total context size estimate including system prompt and messages\n * @param systemPrompt - System prompt text\n * @param messages - Conversation messages\n * @returns Total estimated token count\n */\n estimateContextSize(systemPrompt: string, messages: BaseMessage[]): number {\n const systemTokens = this.estimateSystemPromptTokens(systemPrompt);\n const messageTokens = this.countMessagesTokens(messages);\n \n const completionOverhead = 10;\n \n return systemTokens + messageTokens + completionOverhead;\n }\n\n /**\n * Get the role string for a message\n * @param message - The message to get the role for\n * @returns Role string ('user', 'assistant', 'system', etc.)\n */\n private getMessageRole(message: BaseMessage): string {\n const messageType = message._getType();\n switch (messageType) {\n case 'human':\n return 'user';\n case 'ai':\n return 'assistant';\n case 'system':\n return 'system';\n case 'function':\n return 'function';\n case 'tool':\n return 'tool';\n default:\n return 'user';\n }\n }\n\n /**\n * Get the model name being used for token counting\n * @returns The tiktoken model name\n */\n getModelName(): string {\n return this.modelName;\n }\n\n /**\n * Clean up encoding resources\n */\n dispose(): void {\n try {\n this.encoding.free();\n } catch {\n }\n }\n}","import type { BaseMessage } from '@langchain/core/messages';\nimport { TokenCounter } from './TokenCounter';\n\n/**\n * Result of adding a message to the memory window\n */\nexport interface AddMessageResult {\n /** Whether the message was successfully added */\n added: boolean;\n /** Messages that were pruned to make room */\n prunedMessages: BaseMessage[];\n /** Current token count after operation */\n currentTokenCount: number;\n /** Remaining token capacity */\n remainingCapacity: number;\n}\n\n/**\n * Memory window that manages conversation history with token-based size limits\n * Automatically prunes old messages to stay within token limits while preserving conversational context\n */\nexport class MemoryWindow {\n private messages: BaseMessage[] = [];\n private maxTokens: number;\n private reserveTokens: number;\n private tokenCounter: TokenCounter;\n private systemPrompt: string = '';\n private systemPromptTokens: number = 0;\n\n public static readonly DEFAULT_MAX_TOKENS = 8000;\n public static readonly DEFAULT_RESERVE_TOKENS = 1000;\n public static readonly PRUNING_BATCH_SIZE = 2;\n\n constructor(\n maxTokens: number = MemoryWindow.DEFAULT_MAX_TOKENS,\n reserveTokens: number = MemoryWindow.DEFAULT_RESERVE_TOKENS,\n tokenCounter?: TokenCounter\n ) {\n if (reserveTokens >= maxTokens) {\n throw new Error('Reserve tokens must be less than max tokens');\n }\n\n this.maxTokens = maxTokens;\n this.reserveTokens = reserveTokens;\n this.tokenCounter = tokenCounter || new TokenCounter();\n }\n\n /**\n * Add a message to the memory window, pruning old messages if necessary\n * @param message - The message to add\n * @returns Result of the add operation including any pruned messages\n */\n addMessage(message: BaseMessage): AddMessageResult {\n this.tokenCounter.countMessageTokens(message);\n \n this.messages.push(message);\n \n const currentTokens = this.getCurrentTokenCount();\n const availableTokens = this.maxTokens - this.reserveTokens;\n \n let prunedMessages: BaseMessage[] = [];\n \n if (currentTokens > availableTokens) {\n this.messages.pop();\n \n prunedMessages = this.pruneToFit();\n \n this.messages.push(message);\n }\n\n return {\n added: true,\n prunedMessages,\n currentTokenCount: this.getCurrentTokenCount(),\n remainingCapacity: this.getRemainingTokenCapacity()\n };\n }\n\n /**\n * Prune old messages to fit within token limits\n * Removes messages in pairs to maintain conversational flow\n * @returns Array of pruned messages\n */\n pruneToFit(): BaseMessage[] {\n const prunedMessages: BaseMessage[] = [];\n const targetTokens = this.maxTokens - this.reserveTokens;\n \n while (this.getCurrentTokenCount() > targetTokens && this.messages.length > 0) {\n const batchSize = Math.min(MemoryWindow.PRUNING_BATCH_SIZE, this.messages.length);\n \n for (let i = 0; i < batchSize; i++) {\n const prunedMessage = this.messages.shift();\n if (prunedMessage) {\n prunedMessages.push(prunedMessage);\n }\n }\n \n if (prunedMessages.length > 1000) {\n break;\n }\n }\n\n return prunedMessages;\n }\n\n /**\n * Get current token count including system prompt and messages\n * @returns Current token count\n */\n getCurrentTokenCount(): number {\n const messageTokens = this.tokenCounter.countMessagesTokens(this.messages);\n return this.systemPromptTokens + messageTokens;\n }\n\n /**\n * Get remaining token capacity before hitting the reserve limit\n * @returns Remaining tokens that can be used\n */\n getRemainingTokenCapacity(): number {\n return Math.max(0, this.maxTokens - this.getCurrentTokenCount());\n }\n\n /**\n * Check if a message can be added without exceeding limits\n * @param message - The message to check\n * @returns True if message can be added within reserve limits\n */\n canAddMessage(message: BaseMessage): boolean {\n const messageTokens = this.tokenCounter.countMessageTokens(message);\n const currentTokens = this.getCurrentTokenCount();\n const wouldExceedReserve = (currentTokens + messageTokens) > (this.maxTokens - this.reserveTokens);\n \n if (messageTokens > this.maxTokens) {\n return false;\n }\n \n return !wouldExceedReserve || this.messages.length > 0;\n }\n\n /**\n * Get all messages in the memory window\n * @returns Copy of current messages array\n */\n getMessages(): BaseMessage[] {\n return [...this.messages];\n }\n\n /**\n * Clear all messages from the memory window\n */\n clear(): void {\n this.messages = [];\n }\n\n /**\n * Set the system prompt and update token calculations\n * @param systemPrompt - The system prompt text\n */\n setSystemPrompt(systemPrompt: string): void {\n this.systemPrompt = systemPrompt;\n this.systemPromptTokens = this.tokenCounter.estimateSystemPromptTokens(systemPrompt);\n }\n\n /**\n * Get the current system prompt\n * @returns Current system prompt\n */\n getSystemPrompt(): string {\n return this.systemPrompt;\n }\n\n /**\n * Get current configuration\n * @returns Memory window configuration\n */\n getConfig() {\n return {\n maxTokens: this.maxTokens,\n reserveTokens: this.reserveTokens,\n currentTokens: this.getCurrentTokenCount(),\n messageCount: this.messages.length,\n systemPromptTokens: this.systemPromptTokens\n };\n }\n\n /**\n * Update token limits\n * @param maxTokens - New maximum token limit\n * @param reserveTokens - New reserve token amount\n */\n updateLimits(maxTokens: number, reserveTokens?: number): void {\n if (reserveTokens !== undefined && reserveTokens >= maxTokens) {\n throw new Error('Reserve tokens must be less than max tokens');\n }\n\n this.maxTokens = maxTokens;\n if (reserveTokens !== undefined) {\n this.reserveTokens = reserveTokens;\n }\n\n if (this.getCurrentTokenCount() > (this.maxTokens - this.reserveTokens)) {\n this.pruneToFit();\n }\n }\n\n /**\n * Get statistics about the memory window\n * @returns Memory usage statistics\n */\n getStats() {\n const currentTokens = this.getCurrentTokenCount();\n const capacity = this.maxTokens;\n const usagePercentage = (currentTokens / capacity) * 100;\n \n return {\n totalMessages: this.messages.length,\n currentTokens,\n maxTokens: capacity,\n reserveTokens: this.reserveTokens,\n systemPromptTokens: this.systemPromptTokens,\n usagePercentage: Math.round(usagePercentage * 100) / 100,\n remainingCapacity: this.getRemainingTokenCapacity(),\n canAcceptMore: this.getRemainingTokenCapacity() > this.reserveTokens\n };\n }\n\n /**\n * Clean up resources\n */\n dispose(): void {\n this.clear();\n this.tokenCounter.dispose();\n }\n}","import { createHash } from 'crypto';\nimport { ReferenceId } from '../types/content-reference';\n\n/**\n * Content-based reference ID generator using SHA-256 (HCS-1 style)\n * \n * Generates deterministic reference IDs based on content hashing.\n * Same content always produces the same reference ID.\n */\nexport class ReferenceIdGenerator {\n /**\n * Generate a content-based reference ID using SHA-256 hashing\n * \n * @param content The content to generate a reference ID for\n * @returns Deterministic reference ID based on content hash\n */\n static generateId(content: Buffer): ReferenceId {\n const hash = createHash('sha256');\n hash.update(content);\n return hash.digest('hex');\n }\n \n /**\n * Validate that a string is a properly formatted reference ID\n * \n * @param id The ID to validate\n * @returns true if the ID is valid format\n */\n static isValidReferenceId(id: string): id is ReferenceId {\n if (!id || typeof id !== 'string') {\n return false;\n }\n \n if (id.length !== 64) {\n return false;\n }\n \n return /^[a-f0-9]+$/.test(id);\n }\n \n /**\n * Extract reference ID from ref:// format\n * \n * @param input Input string that may contain a reference ID\n * @returns Extracted reference ID or null if not found\n */\n static extractReferenceId(input: string): ReferenceId | null {\n if (!input || typeof input !== 'string') {\n return null;\n }\n \n const refFormatMatch = input.match(/^ref:\\/\\/([a-f0-9]{64})$/);\n if (refFormatMatch) {\n return refFormatMatch[1] as ReferenceId;\n }\n \n return this.isValidReferenceId(input) ? input : null;\n }\n \n /**\n * Format a reference ID in the standard ref:// format\n * \n * @param referenceId The reference ID to format\n * @returns Formatted reference string\n */\n static formatReference(referenceId: ReferenceId): string {\n return `ref://${referenceId}`;\n }\n \n /**\n * Generate a test reference ID (for testing purposes only)\n * \n * @param testSeed A test seed to generate a fake but valid ID format\n * @returns A valid format reference ID for testing\n */\n static generateTestId(testSeed: string): ReferenceId {\n const content = Buffer.from(`test-${testSeed}-${Date.now()}`);\n return this.generateId(content);\n }\n}","/**\n * Content Reference System Types\n * \n * Shared interfaces for the Reference-Based Content System that handles\n * large content storage with unique reference IDs to optimize context window usage.\n */\n\n/**\n * Unique identifier for stored content references\n * Format: Cryptographically secure 32-byte identifier with base64url encoding\n */\nexport type ReferenceId = string;\n\n/**\n * Lifecycle state of a content reference\n */\nexport type ReferenceLifecycleState = 'active' | 'expired' | 'cleanup_pending' | 'invalid';\n\n/**\n * Content types supported by the reference system\n */\nexport type ContentType = 'text' | 'json' | 'html' | 'markdown' | 'binary' | 'unknown';\n\n/**\n * Sources that created the content reference\n */\nexport type ContentSource = 'mcp_tool' | 'user_upload' | 'agent_generated' | 'system';\n\n/**\n * Metadata associated with stored content\n */\nexport interface ContentMetadata {\n /** Content type classification */\n contentType: ContentType;\n \n /** MIME type of the original content */\n mimeType?: string;\n \n /** Size in bytes of the stored content */\n sizeBytes: number;\n \n /** When the content was originally stored */\n createdAt: Date;\n \n /** Last time the content was accessed via reference resolution */\n lastAccessedAt: Date;\n \n /** Source that created this content reference */\n source: ContentSource;\n \n /** Name of the MCP tool that generated the content (if applicable) */\n mcpToolName?: string;\n \n /** Original filename or suggested name for the content */\n fileName?: string;\n \n /** Number of times this reference has been resolved */\n accessCount: number;\n \n /** Tags for categorization and cleanup policies */\n tags?: string[];\n \n /** Custom metadata from the source */\n customMetadata?: Record<string, unknown>;\n}\n\n/**\n * Core content reference object passed through agent context\n * Designed to be lightweight (<100 tokens) while providing enough \n * information for agent decision-making\n */\nexport interface ContentReference {\n /** Unique identifier for resolving the content */\n referenceId: ReferenceId;\n \n /** Current lifecycle state */\n state: ReferenceLifecycleState;\n \n /** Brief description or preview of the content (max 200 chars) */\n preview: string;\n \n /** Essential metadata for agent decision-making */\n metadata: Pick<ContentMetadata, 'contentType' | 'sizeBytes' | 'source' | 'fileName' | 'mimeType'>;\n \n /** When this reference was created */\n createdAt: Date;\n \n /** Special format indicator for reference IDs in content */\n readonly format: 'ref://{id}';\n}\n\n/**\n * Result of attempting to resolve a content reference\n */\nexport interface ReferenceResolutionResult {\n /** Whether the resolution was successful */\n success: boolean;\n \n /** The resolved content if successful */\n content?: Buffer;\n \n /** Complete metadata if successful */\n metadata?: ContentMetadata;\n \n /** Error message if resolution failed */\n error?: string;\n \n /** Specific error type for targeted error handling */\n errorType?: 'not_found' | 'expired' | 'corrupted' | 'access_denied' | 'system_error';\n \n /** Suggested actions for recovery */\n suggestedActions?: string[];\n}\n\n/**\n * Configuration for content reference storage and lifecycle\n */\nexport interface ContentReferenceConfig {\n /** Size threshold above which content should be stored as references (default: 10KB) */\n sizeThresholdBytes: number;\n \n /** Maximum age for unused references before cleanup (default: 1 hour) */\n maxAgeMs: number;\n \n /** Maximum number of references to store simultaneously */\n maxReferences: number;\n \n /** Maximum total storage size for all references */\n maxTotalStorageBytes: number;\n \n /** Whether to enable automatic cleanup */\n enableAutoCleanup: boolean;\n \n /** Interval for cleanup checks in milliseconds */\n cleanupIntervalMs: number;\n \n /** Whether to persist references across restarts */\n enablePersistence: boolean;\n \n /** Storage backend configuration */\n storageBackend: 'memory' | 'filesystem' | 'hybrid';\n \n /** Cleanup policies for different content types */\n cleanupPolicies: {\n /** Policy for content marked as \"recent\" from MCP tools */\n recent: { maxAgeMs: number; priority: number };\n \n /** Policy for user-uploaded content */\n userContent: { maxAgeMs: number; priority: number };\n \n /** Policy for agent-generated content */\n agentGenerated: { maxAgeMs: number; priority: number };\n \n /** Default policy for other content */\n default: { maxAgeMs: number; priority: number };\n };\n}\n\n/**\n * Default configuration values\n */\nexport const DEFAULT_CONTENT_REFERENCE_CONFIG: ContentReferenceConfig = {\n sizeThresholdBytes: 10 * 1024,\n maxAgeMs: 60 * 60 * 1000,\n maxReferences: 100,\n maxTotalStorageBytes: 100 * 1024 * 1024,\n enableAutoCleanup: true,\n cleanupIntervalMs: 5 * 60 * 1000,\n enablePersistence: false,\n storageBackend: 'memory',\n cleanupPolicies: {\n recent: { maxAgeMs: 30 * 60 * 1000, priority: 1 },\n userContent: { maxAgeMs: 2 * 60 * 60 * 1000, priority: 2 },\n agentGenerated: { maxAgeMs: 60 * 60 * 1000, priority: 3 },\n default: { maxAgeMs: 60 * 60 * 1000, priority: 4 }\n }\n};\n\n/**\n * Statistics about content reference usage and storage\n */\nexport interface ContentReferenceStats {\n /** Total number of active references */\n activeReferences: number;\n \n /** Total storage used by all references in bytes */\n totalStorageBytes: number;\n \n /** Number of references cleaned up in last cleanup cycle */\n recentlyCleanedUp: number;\n \n /** Number of successful reference resolutions since startup */\n totalResolutions: number;\n \n /** Number of failed resolution attempts */\n failedResolutions: number;\n \n /** Average content size in bytes */\n averageContentSize: number;\n \n /** Most frequently accessed reference ID */\n mostAccessedReferenceId?: ReferenceId;\n \n /** Storage utilization percentage */\n storageUtilization: number;\n \n /** Performance metrics */\n performanceMetrics: {\n /** Average time to create a reference in milliseconds */\n averageCreationTimeMs: number;\n \n /** Average time to resolve a reference in milliseconds */\n averageResolutionTimeMs: number;\n \n /** Average cleanup time in milliseconds */\n averageCleanupTimeMs: number;\n };\n}\n\n/**\n * Error types for content reference operations\n */\nexport class ContentReferenceError extends Error {\n constructor(\n message: string,\n public readonly type: ReferenceResolutionResult['errorType'],\n public readonly referenceId?: ReferenceId,\n public readonly suggestedActions?: string[]\n ) {\n super(message);\n this.name = 'ContentReferenceError';\n }\n}\n\n/**\n * Interface for content reference storage implementations\n */\nexport interface ContentReferenceStore {\n /**\n * Store content and return a reference\n */\n storeContent(\n content: Buffer,\n metadata: Omit<ContentMetadata, 'createdAt' | 'lastAccessedAt' | 'accessCount'>\n ): Promise<ContentReference>;\n \n /**\n * Resolve a reference to its content\n */\n resolveReference(referenceId: ReferenceId): Promise<ReferenceResolutionResult>;\n \n /**\n * Check if a reference exists and is valid\n */\n hasReference(referenceId: ReferenceId): Promise<boolean>;\n \n /**\n * Mark a reference for cleanup\n */\n cleanupReference(referenceId: ReferenceId): Promise<boolean>;\n \n /**\n * Get current storage statistics\n */\n getStats(): Promise<ContentReferenceStats>;\n \n /**\n * Update configuration\n */\n updateConfig(config: Partial<ContentReferenceConfig>): Promise<void>;\n \n /**\n * Perform cleanup based on current policies\n */\n performCleanup(): Promise<{ cleanedUp: number; errors: string[] }>;\n \n /**\n * Dispose of resources\n */\n dispose(): Promise<void>;\n}","import type { BaseMessage } from '@langchain/core/messages';\nimport { ReferenceIdGenerator } from './ReferenceIdGenerator';\nimport {\n ReferenceId,\n ContentReference,\n ContentMetadata,\n ReferenceResolutionResult,\n ContentReferenceConfig,\n ContentReferenceStore,\n ContentReferenceStats,\n ContentReferenceError,\n ContentType,\n ContentSource,\n ReferenceLifecycleState,\n DEFAULT_CONTENT_REFERENCE_CONFIG\n} from '../types/content-reference';\n\n/**\n * Stored message with metadata\n */\ninterface StoredMessage {\n message: BaseMessage;\n storedAt: Date;\n id: string;\n}\n\n/**\n * Search options for message queries\n */\ninterface SearchOptions {\n /** Whether to perform case-sensitive search */\n caseSensitive?: boolean;\n /** Maximum number of results to return */\n limit?: number;\n /** Whether to use regex pattern matching */\n useRegex?: boolean;\n}\n\n/**\n * Result of storing messages\n */\ninterface StoreResult {\n /** Number of messages successfully stored */\n stored: number;\n /** Number of old messages dropped to make room */\n dropped: number;\n}\n\n/**\n * Storage statistics\n */\nexport interface StorageStats {\n /** Total number of messages currently stored */\n totalMessages: number;\n /** Maximum storage capacity */\n maxStorageLimit: number;\n /** Percentage of storage used */\n usagePercentage: number;\n /** Timestamp of oldest message */\n oldestMessageTime: Date | undefined;\n /** Timestamp of newest message */\n newestMessageTime: Date | undefined;\n}\n\n/**\n * Stored content with reference metadata\n */\ninterface StoredContent {\n /** The actual content buffer */\n content: Buffer;\n \n /** Complete metadata */\n metadata: ContentMetadata;\n \n /** Current lifecycle state */\n state: ReferenceLifecycleState;\n \n /** When this reference expires (if applicable) */\n expiresAt?: Date;\n}\n\n/**\n * Content storage for managing pruned conversation messages and large content references\n * Provides searchable storage with time-based querying and automatic cleanup.\n * \n * Extended to support reference-based storage for large content to optimize context window usage.\n */\nexport class ContentStorage implements ContentReferenceStore {\n private messages: StoredMessage[] = [];\n private maxStorage: number;\n private idCounter: number = 0;\n\n private contentStore: Map<ReferenceId, StoredContent> = new Map();\n private referenceConfig: ContentReferenceConfig;\n private cleanupTimer?: NodeJS.Timeout;\n private referenceStats: Omit<ContentReferenceStats, 'performanceMetrics'> & {\n performanceMetrics: ContentReferenceStats['performanceMetrics'] & {\n creationTimes: number[];\n resolutionTimes: number[];\n cleanupTimes: number[];\n };\n };\n\n public static readonly DEFAULT_MAX_STORAGE = 1000;\n\n constructor(\n maxStorage: number = ContentStorage.DEFAULT_MAX_STORAGE,\n referenceConfig?: Partial<ContentReferenceConfig>\n ) {\n this.maxStorage = maxStorage;\n \n this.referenceConfig = { ...DEFAULT_CONTENT_REFERENCE_CONFIG, ...referenceConfig };\n this.referenceStats = {\n activeReferences: 0,\n totalStorageBytes: 0,\n recentlyCleanedUp: 0,\n totalResolutions: 0,\n failedResolutions: 0,\n averageContentSize: 0,\n storageUtilization: 0,\n performanceMetrics: {\n averageCreationTimeMs: 0,\n averageResolutionTimeMs: 0,\n averageCleanupTimeMs: 0,\n creationTimes: [],\n resolutionTimes: [],\n cleanupTimes: []\n }\n };\n \n if (this.referenceConfig.enableAutoCleanup) {\n this.startReferenceCleanupTimer();\n }\n }\n\n /**\n * Store messages in the content storage\n * Automatically drops oldest messages if storage limit is exceeded\n * @param messages - Messages to store\n * @returns Result indicating how many messages were stored and dropped\n */\n storeMessages(messages: BaseMessage[]): StoreResult {\n if (messages.length === 0) {\n return { stored: 0, dropped: 0 };\n }\n\n const now = new Date();\n let dropped = 0;\n\n const storedMessages: StoredMessage[] = messages.map(message => ({\n message,\n storedAt: now,\n id: this.generateId()\n }));\n\n this.messages.push(...storedMessages);\n\n while (this.messages.length > this.maxStorage) {\n this.messages.shift();\n dropped++;\n }\n\n return {\n stored: storedMessages.length,\n dropped\n };\n }\n\n /**\n * Get the most recent messages from storage\n * @param count - Number of recent messages to retrieve\n * @returns Array of recent messages in chronological order\n */\n getRecentMessages(count: number): BaseMessage[] {\n if (count <= 0 || this.messages.length === 0) {\n return [];\n }\n\n const startIndex = Math.max(0, this.messages.length - count);\n return this.messages\n .slice(startIndex)\n .map(stored => stored.message);\n }\n\n /**\n * Search for messages containing specific text or patterns\n * @param query - Search term or regex pattern\n * @param options - Search configuration options\n * @returns Array of matching messages\n */\n searchMessages(query: string, options: SearchOptions = {}): BaseMessage[] {\n if (!query || this.messages.length === 0) {\n return [];\n }\n\n const {\n caseSensitive = false,\n limit,\n useRegex = false\n } = options;\n\n let matches: BaseMessage[] = [];\n\n if (useRegex) {\n try {\n const regex = new RegExp(query, caseSensitive ? 'g' : 'gi');\n matches = this.messages\n .filter(stored => regex.test(stored.message.content as string))\n .map(stored => stored.message);\n } catch (error) {\n return [];\n }\n } else {\n const searchTerm = caseSensitive ? query : query.toLowerCase();\n matches = this.messages\n .filter(stored => {\n const content = stored.message.content as string;\n const searchContent = caseSensitive ? content : content.toLowerCase();\n return searchContent.includes(searchTerm);\n })\n .map(stored => stored.message);\n }\n\n return limit ? matches.slice(0, limit) : matches;\n }\n\n /**\n * Get messages from a specific time range\n * @param startTime - Start of time range (inclusive)\n * @param endTime - End of time range (inclusive)\n * @returns Array of messages within the time range\n */\n getMessagesFromTimeRange(startTime: Date, endTime: Date): BaseMessage[] {\n if (startTime > endTime || this.messages.length === 0) {\n return [];\n }\n\n return this.messages\n .filter(stored => \n stored.storedAt >= startTime && stored.storedAt <= endTime\n )\n .map(stored => stored.message);\n }\n\n /**\n * Get storage statistics and usage information\n * @returns Current storage statistics\n */\n getStorageStats(): StorageStats {\n const totalMessages = this.messages.length;\n const usagePercentage = totalMessages > 0 \n ? Math.round((totalMessages / this.maxStorage) * 100)\n : 0;\n\n let oldestMessageTime: Date | undefined;\n let newestMessageTime: Date | undefined;\n\n if (totalMessages > 0) {\n oldestMessageTime = this.messages[0].storedAt;\n newestMessageTime = this.messages[totalMessages - 1].storedAt;\n }\n\n return {\n totalMessages,\n maxStorageLimit: this.maxStorage,\n usagePercentage,\n oldestMessageTime,\n newestMessageTime\n };\n }\n\n /**\n * Clear all stored messages\n */\n clear(): void {\n this.messages = [];\n this.idCounter = 0;\n }\n\n /**\n * Get total number of stored messages\n * @returns Number of messages currently in storage\n */\n getTotalStoredMessages(): number {\n return this.messages.length;\n }\n\n /**\n * Update the maximum storage limit\n * @param newLimit - New maximum storage limit\n */\n updateStorageLimit(newLimit: number): void {\n if (newLimit <= 0) {\n throw new Error('Storage limit must be greater than 0');\n }\n\n this.maxStorage = newLimit;\n\n while (this.messages.length > this.maxStorage) {\n this.messages.shift();\n }\n }\n\n /**\n * Get messages by message type\n * @param messageType - Type of messages to retrieve ('human', 'ai', 'system', etc.)\n * @param limit - Maximum number of messages to return\n * @returns Array of messages of the specified type\n */\n getMessagesByType(messageType: string, limit?: number): BaseMessage[] {\n const filtered = this.messages\n .filter(stored => stored.message._getType() === messageType)\n .map(stored => stored.message);\n\n return limit ? filtered.slice(0, limit) : filtered;\n }\n\n /**\n * Get the current storage configuration\n * @returns Storage configuration object\n */\n getConfig() {\n return {\n maxStorage: this.maxStorage,\n currentUsage: this.messages.length,\n utilizationPercentage: (this.messages.length / this.maxStorage) * 100\n };\n }\n\n /**\n * Generate a unique ID for stored messages\n * @returns Unique string identifier\n */\n private generateId(): string {\n return `msg_${++this.idCounter}_${Date.now()}`;\n }\n\n /**\n * Get messages stored within the last N minutes\n * @param minutes - Number of minutes to look back\n * @returns Array of messages from the last N minutes\n */\n getRecentMessagesByTime(minutes: number): BaseMessage[] {\n if (minutes <= 0 || this.messages.length === 0) {\n return [];\n }\n\n const cutoffTime = new Date(Date.now() - (minutes * 60 * 1000));\n \n return this.messages\n .filter(stored => stored.storedAt >= cutoffTime)\n .map(stored => stored.message);\n }\n\n /**\n * Export messages to a JSON-serializable format\n * @returns Serializable representation of stored messages\n */\n exportMessages() {\n return this.messages.map(stored => ({\n content: stored.message.content,\n type: stored.message._getType(),\n storedAt: stored.storedAt.toISOString(),\n id: stored.id\n }));\n }\n\n\n /**\n * Determine if content should be stored as a reference based on size\n */\n shouldUseReference(content: Buffer | string): boolean {\n const size = Buffer.isBuffer(content) ? content.length : Buffer.byteLength(content, 'utf8');\n return size > this.referenceConfig.sizeThresholdBytes;\n }\n\n /**\n * Store content and return a reference if it exceeds the size threshold\n * Otherwise returns null to indicate direct content should be used\n */\n async storeContentIfLarge(\n content: Buffer | string,\n metadata: {\n contentType?: ContentType;\n mimeType?: string;\n source: ContentSource;\n mcpToolName?: string;\n fileName?: string;\n tags?: string[];\n customMetadata?: Record<string, unknown>;\n }\n ): Promise<ContentReference | null> {\n const buffer = Buffer.isBuffer(content) ? content : Buffer.from(content, 'utf8');\n \n if (!this.shouldUseReference(buffer)) {\n return null;\n }\n \n const storeMetadata: Omit<ContentMetadata, 'createdAt' | 'lastAccessedAt' | 'accessCount'> = {\n contentType: metadata.contentType || this.detectContentType(buffer, metadata.mimeType),\n sizeBytes: buffer.length,\n source: metadata.source,\n tags: []\n };\n \n if (metadata.mimeType !== undefined) {\n storeMetadata.mimeType = metadata.mimeType;\n }\n if (metadata.mcpToolName !== undefined) {\n storeMetadata.mcpToolName = metadata.mcpToolName;\n }\n if (metadata.fileName !== undefined) {\n storeMetadata.fileName = metadata.fileName;\n }\n if (metadata.tags !== undefined) {\n storeMetadata.tags = metadata.tags;\n }\n if (metadata.customMetadata !== undefined) {\n storeMetadata.customMetadata = metadata.customMetadata;\n }\n \n return await this.storeContent(buffer, storeMetadata);\n }\n\n /**\n * Store content and return a reference (implements ContentReferenceStore)\n */\n async storeContent(\n content: Buffer,\n metadata: Omit<ContentMetadata, 'createdAt' | 'lastAccessedAt' | 'accessCount'>\n ): Promise<ContentReference> {\n const startTime = Date.now();\n \n try {\n const now = new Date();\n const referenceId = ReferenceIdGenerator.generateId(content);\n \n const fullMetadata: ContentMetadata = {\n ...metadata,\n createdAt: now,\n lastAccessedAt: now,\n accessCount: 0\n };\n \n const storedContent: StoredContent = {\n content,\n metadata: fullMetadata,\n state: 'active'\n };\n \n const expirationTime = this.calculateExpirationTime(metadata.source);\n if (expirationTime !== undefined) {\n storedContent.expiresAt = expirationTime;\n }\n \n this.contentStore.set(referenceId, storedContent);\n \n this.updateStatsAfterStore(content.length);\n \n await this.enforceReferenceStorageLimits();\n \n const preview = this.createContentPreview(content, fullMetadata.contentType);\n \n const referenceMetadata: Pick<ContentMetadata, 'contentType' | 'sizeBytes' | 'source' | 'fileName' | 'mimeType'> = {\n contentType: fullMetadata.contentType,\n sizeBytes: fullMetadata.sizeBytes,\n source: fullMetadata.source\n };\n \n if (fullMetadata.fileName !== undefined) {\n referenceMetadata.fileName = fullMetadata.fileName;\n }\n if (fullMetadata.mimeType !== undefined) {\n referenceMetadata.mimeType = fullMetadata.mimeType;\n }\n \n const reference: ContentReference = {\n referenceId,\n state: 'active',\n preview,\n metadata: referenceMetadata,\n createdAt: now,\n format: 'ref://{id}' as const\n };\n \n const duration = Date.now() - startTime;\n this.recordPerformanceMetric('creation', duration);\n \n return reference;\n } catch (error) {\n const duration = Date.now() - startTime;\n this.recordPerformanceMetric('creation', duration);\n \n throw new ContentReferenceError(\n `Failed to store content: ${error instanceof Error ? error.message : 'Unknown error'}`,\n 'system_error',\n undefined,\n ['Try again', 'Check storage limits', 'Contact administrator']\n );\n }\n }\n\n /**\n * Resolve a reference to its content (implements ContentReferenceStore)\n */\n async resolveReference(referenceId: ReferenceId): Promise<ReferenceResolutionResult> {\n const startTime = Date.now();\n \n try {\n if (!ReferenceIdGenerator.isValidReferenceId(referenceId)) {\n this.referenceStats.failedResolutions++;\n return {\n success: false,\n error: 'Invalid reference ID format',\n errorType: 'not_found',\n suggestedActions: ['Check the reference ID format', 'Ensure the reference ID is complete']\n };\n }\n \n const storedContent = this.contentStore.get(referenceId);\n \n if (!storedContent) {\n this.referenceStats.failedResolutions++;\n return {\n success: false,\n error: 'Reference not found',\n errorType: 'not_found',\n suggestedActions: ['Verify the reference ID', 'Check if the content has expired', 'Request fresh content']\n };\n }\n \n if (storedContent.expiresAt && storedContent.expiresAt < new Date()) {\n storedContent.state = 'expired';\n this.referenceStats.failedResolutions++;\n return {\n success: false,\n error: 'Reference has expired',\n errorType: 'expired',\n suggestedActions: ['Request fresh content', 'Use alternative content source']\n };\n }\n \n if (storedContent.state !== 'active') {\n this.referenceStats.failedResolutions++;\n return {\n success: false,\n error: `Reference is ${storedContent.state}`,\n errorType: storedContent.state === 'expired' ? 'expired' : 'corrupted',\n suggestedActions: ['Request fresh content', 'Check reference validity']\n };\n }\n \n storedContent.metadata.lastAccessedAt = new Date();\n storedContent.metadata.accessCount++;\n \n this.referenceStats.totalResolutions++;\n \n const duration = Date.now() - startTime;\n this.recordPerformanceMetric('resolution', duration);\n \n return {\n success: true,\n content: storedContent.content,\n metadata: storedContent.metadata\n };\n } catch (error) {\n const duration = Date.now() - startTime;\n this.recordPerformanceMetric('resolution', duration);\n \n this.referenceStats.failedResolutions++;\n \n return {\n success: false,\n error: `System error resolving reference: ${error instanceof Error ? error.message : 'Unknown error'}`,\n errorType: 'system_error',\n suggestedActions: ['Try again', 'Contact administrator']\n };\n }\n }\n\n /**\n * Check if a reference exists and is valid\n */\n async hasReference(referenceId: ReferenceId): Promise<boolean> {\n if (!ReferenceIdGenerator.isValidReferenceId(referenceId)) {\n return false;\n }\n \n const storedContent = this.contentStore.get(referenceId);\n if (!storedContent) {\n return false;\n }\n \n if (storedContent.expiresAt && storedContent.expiresAt < new Date()) {\n storedContent.state = 'expired';\n return false;\n }\n \n return storedContent.state === 'active';\n }\n\n /**\n * Mark a reference for cleanup\n */\n async cleanupReference(referenceId: ReferenceId): Promise<boolean> {\n const storedContent = this.contentStore.get(referenceId);\n if (!storedContent) {\n return false;\n }\n \n this.referenceStats.totalStorageBytes -= storedContent.content.length;\n this.referenceStats.activeReferences--;\n this.referenceStats.recentlyCleanedUp++;\n \n this.contentStore.delete(referenceId);\n \n return true;\n }\n\n /**\n * Get current reference storage statistics (implements ContentReferenceStore)\n */\n async getStats(): Promise<ContentReferenceStats> {\n this.updateReferenceStorageStats();\n \n return {\n ...this.referenceStats,\n performanceMetrics: {\n averageCreationTimeMs: this.calculateAverage(this.referenceStats.performanceMetrics.creationTimes),\n averageResolutionTimeMs: this.calculateAverage(this.referenceStats.performanceMetrics.resolutionTimes),\n averageCleanupTimeMs: this.calculateAverage(this.referenceStats.performanceMetrics.cleanupTimes)\n }\n };\n }\n\n /**\n * Update reference configuration\n */\n async updateConfig(config: Partial<ContentReferenceConfig>): Promise<void> {\n this.referenceConfig = { ...this.referenceConfig, ...config };\n \n if (this.cleanupTimer) {\n clearInterval(this.cleanupTimer);\n delete this.cleanupTimer;\n }\n \n if (this.referenceConfig.enableAutoCleanup) {\n this.startReferenceCleanupTimer();\n }\n }\n\n /**\n * Perform cleanup based on current policies (implements ContentReferenceStore)\n */\n async performCleanup(): Promise<{ cleanedUp: number; errors: string[] }> {\n const startTime = Date.now();\n const errors: string[] = [];\n let cleanedUp = 0;\n \n try {\n const now = new Date();\n const toCleanup: ReferenceId[] = [];\n \n for (const [referenceId, storedContent] of this.contentStore.entries()) {\n let shouldCleanup = false;\n \n if (storedContent.expiresAt && storedContent.expiresAt < now) {\n shouldCleanup = true;\n storedContent.state = 'expired';\n }\n \n const ageMs = now.getTime() - storedContent.metadata.createdAt.getTime();\n const policy = this.getCleanupPolicy(storedContent.metadata.source);\n \n if (ageMs > policy.maxAgeMs) {\n shouldCleanup = true;\n }\n \n if (storedContent.state === 'cleanup_pending') {\n shouldCleanup = true;\n }\n \n if (shouldCleanup) {\n toCleanup.push(referenceId);\n }\n }\n \n toCleanup.sort((a, b) => {\n const aContent = this.contentStore.get(a)!;\n const bContent = this.contentStore.get(b)!;\n const aPriority = this.getCleanupPolicy(aContent.metadata.source).priority;\n const bPriority = this.getCleanupPolicy(bContent.metadata.source).priority;\n return bPriority - aPriority;\n });\n \n for (const referenceId of toCleanup) {\n try {\n const success = await this.cleanupReference(referenceId);\n if (success) {\n cleanedUp++;\n }\n } catch (error) {\n errors.push(`Failed to cleanup ${referenceId}: ${error instanceof Error ? error.message : 'Unknown error'}`);\n }\n }\n \n if (this.contentStore.size > this.referenceConfig.maxReferences) {\n const sortedByAge = Array.from(this.contentStore.entries())\n .sort(([, a], [, b]) => a.metadata.lastAccessedAt.getTime() - b.metadata.lastAccessedAt.getTime());\n \n const excessCount = this.contentStore.size - this.referenceConfig.maxReferences;\n for (let i = 0; i < excessCount && i < sortedByAge.length; i++) {\n const [referenceId] = sortedByAge[i];\n try {\n const success = await this.cleanupReference(referenceId);\n if (success) {\n cleanedUp++;\n }\n } catch (error) {\n errors.push(`Failed to cleanup excess reference ${referenceId}: ${error instanceof Error ? error.message : 'Unknown error'}`);\n }\n }\n }\n \n const duration = Date.now() - startTime;\n this.recordPerformanceMetric('cleanup', duration);\n \n return { cleanedUp, errors };\n } catch (error) {\n const duration = Date.now() - startTime;\n this.recordPerformanceMetric('cleanup', duration);\n \n const errorMessage = `Cleanup process failed: ${error instanceof Error ? error.message : 'Unknown error'}`;\n errors.push(errorMessage);\n \n return { cleanedUp, errors };\n }\n }\n\n /**\n * Get reference configuration for debugging\n */\n getReferenceConfig(): ContentReferenceConfig {\n return { ...this.referenceConfig };\n }\n\n\n private async enforceReferenceStorageLimits(): Promise<void> {\n if (this.contentStore.size >= this.referenceConfig.maxReferences) {\n await this.performCleanup();\n }\n \n if (this.referenceStats.totalStorageBytes >= this.referenceConfig.maxTotalStorageBytes) {\n await this.performCleanup();\n }\n }\n\n private calculateExpirationTime(source: ContentSource): Date | undefined {\n const policy = this.getCleanupPolicy(source);\n return new Date(Date.now() + policy.maxAgeMs);\n }\n\n private getCleanupPolicy(source: ContentSource) {\n switch (source) {\n case 'mcp_tool':\n return this.referenceConfig.cleanupPolicies.recent;\n case 'user_upload':\n return this.referenceConfig.cleanupPolicies.userContent;\n case 'agent_generated':\n return this.referenceConfig.cleanupPolicies.agentGenerated;\n default:\n return this.referenceConfig.cleanupPolicies.default;\n }\n }\n\n private detectContentType(content: Buffer, mimeType?: string): ContentType {\n if (mimeType) {\n if (mimeType === 'text/html') return 'html';\n if (mimeType === 'text/markdown') return 'markdown';\n if (mimeType === 'application/json') return 'json';\n if (mimeType.startsWith('text/')) return 'text';\n return 'binary';\n }\n \n const contentStr = content.toString('utf8', 0, Math.min(content.length, 1000));\n if (contentStr.startsWith('{') || contentStr.startsWith('[')) return 'json';\n if (contentStr.includes('<html>') || contentStr.includes('<!DOCTYPE')) return 'html';\n if (contentStr.includes('#') && contentStr.includes('\\n')) return 'markdown';\n \n return 'text';\n }\n\n private createContentPreview(content: Buffer, contentType: ContentType): string {\n const maxLength = 200;\n let preview = content.toString('utf8', 0, Math.min(content.length, maxLength * 2));\n \n if (contentType === 'html') {\n preview = preview\n .replace(/<[^>]*>/g, '')\n .replace(/\\s+/g, ' ')\n .trim();\n } else if (contentType === 'json') {\n try {\n const parsed = JSON.parse(preview);\n preview = JSON.stringify(parsed, null, 0);\n } catch {\n }\n }\n \n preview = preview.trim();\n if (preview.length > maxLength) {\n preview = preview.substring(0, maxLength) + '...';\n }\n \n return preview || '[Binary content]';\n }\n\n private updateStatsAfterStore(sizeBytes: number): void {\n this.referenceStats.activeReferences++;\n this.referenceStats.totalStorageBytes += sizeBytes;\n this.updateReferenceStorageStats();\n }\n\n private updateReferenceStorageStats(): void {\n if (this.referenceStats.activeReferences > 0) {\n this.referenceStats.averageContentSize = this.referenceStats.totalStorageBytes / this.referenceStats.activeReferences;\n }\n \n this.referenceStats.storageUtilization = (this.referenceStats.totalStorageBytes / this.referenceConfig.maxTotalStorageBytes) * 100;\n \n let mostAccessedId: ReferenceId | undefined;\n let maxAccess = 0;\n \n for (const [referenceId, storedContent] of this.contentStore.entries()) {\n if (storedContent.metadata.accessCount > maxAccess) {\n maxAccess = storedContent.metadata.accessCount;\n mostAccessedId = referenceId;\n }\n }\n \n if (mostAccessedId !== undefined) {\n this.referenceStats.mostAccessedReferenceId = mostAccessedId;\n } else {\n delete this.referenceStats.mostAccessedReferenceId;\n }\n }\n\n private recordPerformanceMetric(type: 'creation' | 'resolution' | 'cleanup', timeMs: number): void {\n const metrics = this.referenceStats.performanceMetrics;\n const maxRecords = 100;\n \n switch (type) {\n case 'creation':\n metrics.creationTimes.push(timeMs);\n if (metrics.creationTimes.length > maxRecords) {\n metrics.creationTimes.shift();\n }\n break;\n case 'resolution':\n metrics.resolutionTimes.push(timeMs);\n if (metrics.resolutionTimes.length > maxRecords) {\n metrics.resolutionTimes.shift();\n }\n break;\n case 'cleanup':\n metrics.cleanupTimes.push(timeMs);\n if (metrics.cleanupTimes.length > maxRecords) {\n metrics.cleanupTimes.shift();\n }\n break;\n }\n }\n\n private calculateAverage(times: number[]): number {\n if (times.length === 0) return 0;\n return times.reduce((sum, time) => sum + time, 0) / times.length;\n }\n\n private startReferenceCleanupTimer(): void {\n this.cleanupTimer = setInterval(async () => {\n try {\n await this.performCleanup();\n } catch (error) {\n }\n }, this.referenceConfig.cleanupIntervalMs);\n }\n\n /**\n * Clean up resources (enhanced to include reference cleanup)\n */\n async dispose(): Promise<void> {\n if (this.cleanupTimer) {\n clearInterval(this.cleanupTimer);\n delete this.cleanupTimer;\n }\n \n this.contentStore.clear();\n \n this.clear();\n }\n}","import type { BaseMessage } from '@langchain/core/messages';\nimport { MemoryWindow } from './MemoryWindow';\nimport { ContentStorage } from './ContentStorage';\nimport { TokenCounter } from './TokenCounter';\n\n/**\n * Entity association for storing blockchain entity contexts\n */\nexport interface EntityAssociation {\n /** The blockchain entity ID (e.g., tokenId, accountId, topicId) */\n entityId: string;\n /** User-provided or derived friendly name */\n entityName: string;\n /** Type of entity (token, account, topic, schedule, etc.) */\n entityType: string;\n /** When the entity was created/associated */\n createdAt: Date;\n /** Transaction ID that created this entity */\n transactionId?: string;\n}\n\n/**\n * Options for resolving entity references\n */\nexport interface EntityResolutionOptions {\n /** Filter by specific entity type */\n entityType?: string;\n /** Maximum number of results to return */\n limit?: number;\n /** Whether to use fuzzy matching for natural language queries */\n fuzzyMatch?: boolean;\n}\n\n/**\n * Configuration for SmartMemoryManager\n */\nexport interface SmartMemoryConfig {\n /** Maximum tokens for active memory window */\n maxTokens?: number;\n /** Reserve tokens for response generation */\n reserveTokens?: number;\n /** Model name for token counting */\n modelName?: string;\n /** Maximum messages to store in content storage */\n storageLimit?: number;\n}\n\n/**\n * Search options for history search\n */\nexport interface SearchOptions {\n /** Whether to perform case-sensitive search */\n caseSensitive?: boolean;\n /** Maximum number of results to return */\n limit?: number;\n /** Whether to use regex pattern matching */\n useRegex?: boolean;\n}\n\n/**\n * Memory statistics for active memory window\n */\nexport interface MemoryStats {\n /** Total active messages in memory window */\n totalActiveMessages: number;\n /** Current token count including system prompt */\n currentTokenCount: number;\n /** Maximum token capacity */\n maxTokens: number;\n /** Remaining token capacity */\n remainingCapacity: number;\n /** System prompt token count */\n systemPromptTokens: number;\n /** Memory usage percentage */\n usagePercentage: number;\n}\n\nconst IS_ENTITY_ASSOCIATION_FLAG = '\"isEntityAssociation\":true';\n\n\n/**\n * TODO: investigate using chroma / rag for long term memory\n * Smart memory manager that combines active memory window with long-term storage\n * Provides context-aware memory management with automatic pruning and searchable history\n */\nexport class SmartMemoryManager {\n private memoryWindow: MemoryWindow;\n private _contentStorage: ContentStorage;\n private tokenCounter: TokenCounter;\n private config: Required<SmartMemoryConfig>;\n\n private static readonly DEFAULT_CONFIG: Required<SmartMemoryConfig> = {\n maxTokens: 8000,\n reserveTokens: 1000,\n modelName: 'gpt-4o',\n storageLimit: 1000,\n };\n\n constructor(config: SmartMemoryConfig = {}) {\n this.config = { ...SmartMemoryManager.DEFAULT_CONFIG, ...config };\n\n this.tokenCounter = new TokenCounter(this.config.modelName);\n this._contentStorage = new ContentStorage(this.config.storageLimit);\n this.memoryWindow = new MemoryWindow(\n this.config.maxTokens,\n this.config.reserveTokens,\n this.tokenCounter\n );\n }\n\n /**\n * Get the content storage instance for file/content reference operations\n * @returns ContentStorage instance\n */\n get contentStorage(): ContentStorage {\n return this._contentStorage;\n }\n\n /**\n * Add a message to the active memory window\n * Automatically handles pruning and storage of displaced messages\n * @param message - Message to add\n */\n addMessage(message: BaseMessage): void {\n const result = this.memoryWindow.addMessage(message);\n\n if (result.prunedMessages.length > 0) {\n this._contentStorage.storeMessages(result.prunedMessages);\n }\n }\n\n /**\n * Get all active messages from the memory window\n * @returns Array of active messages in chronological order\n */\n getMessages(): BaseMessage[] {\n return this.memoryWindow.getMessages();\n }\n\n /**\n * Clear active memory window\n * @param clearStorage - Whether to also clear the content storage (default: false)\n */\n clear(clearStorage: boolean = false): void {\n this.memoryWindow.clear();\n\n if (clearStorage) {\n this._contentStorage.clear();\n }\n }\n\n /**\n * Set the system prompt for the memory window\n * @param systemPrompt - System prompt text\n */\n setSystemPrompt(systemPrompt: string): void {\n this.memoryWindow.setSystemPrompt(systemPrompt);\n }\n\n /**\n * Get the current system prompt\n * @returns Current system prompt text\n */\n getSystemPrompt(): string {\n return this.memoryWindow.getSystemPrompt();\n }\n\n /**\n * Search through stored message history\n * @param query - Search term or pattern\n * @param options - Search configuration\n * @returns Array of matching messages from history\n */\n searchHistory(query: string, options: SearchOptions = {}): BaseMessage[] {\n return this._contentStorage.searchMessages(query, options);\n }\n\n /**\n * Get recent messages from storage history\n * @param count - Number of recent messages to retrieve\n * @returns Array of recent messages from storage\n */\n getRecentHistory(count: number): BaseMessage[] {\n return this._contentStorage.getRecentMessages(count);\n }\n\n /**\n * Check if a message can be added without exceeding limits\n * @param message - Message to test\n * @returns True if message can be added\n */\n canAddMessage(message: BaseMessage): boolean {\n return this.memoryWindow.canAddMessage(message);\n }\n\n /**\n * Get statistics about the active memory window\n * @returns Memory usage statistics\n */\n getMemoryStats(): MemoryStats {\n const windowStats = this.memoryWindow.getStats();\n\n return {\n totalActiveMessages: windowStats.totalMessages,\n currentTokenCount: windowStats.currentTokens,\n maxTokens: windowStats.maxTokens,\n remainingCapacity: windowStats.remainingCapacity,\n systemPromptTokens: windowStats.systemPromptTokens,\n usagePercentage: windowStats.usagePercentage,\n };\n }\n\n /**\n * Get statistics about the content storage\n * @returns Storage usage statistics\n */\n getStorageStats(): ReturnType<ContentStorage['getStorageStats']> {\n return this._contentStorage.getStorageStats();\n }\n\n /**\n * Get combined statistics for both active memory and storage\n * @returns Combined memory and storage statistics\n */\n getOverallStats(): {\n activeMemory: MemoryStats;\n storage: ReturnType<ContentStorage['getStorageStats']>;\n totalMessagesManaged: number;\n activeMemoryUtilization: number;\n storageUtilization: number;\n } {\n const memoryStats = this.getMemoryStats();\n const storageStats = this.getStorageStats();\n\n return {\n activeMemory: memoryStats,\n storage: storageStats,\n totalMessagesManaged:\n memoryStats.totalActiveMessages + storageStats.totalMessages,\n activeMemoryUtilization: memoryStats.usagePercentage,\n storageUtilization: storageStats.usagePercentage,\n };\n }\n\n /**\n * Update the configuration and apply changes\n * @param newConfig - New configuration options\n */\n updateConfig(newConfig: Partial<SmartMemoryConfig>): void {\n this.config = { ...this.config, ...newConfig };\n\n if (\n newConfig.maxTokens !== undefined ||\n newConfig.reserveTokens !== undefined\n ) {\n this.memoryWindow.updateLimits(\n this.config.maxTokens,\n this.config.reserveTokens\n );\n }\n\n if (newConfig.storageLimit !== undefined) {\n this._contentStorage.updateStorageLimit(this.config.storageLimit);\n }\n }\n\n /**\n * Get current configuration\n * @returns Current configuration settings\n */\n getConfig(): Required<SmartMemoryConfig> {\n return { ...this.config };\n }\n\n /**\n * Get messages from storage within a time range\n * @param startTime - Start of time range\n * @param endTime - End of time range\n * @returns Messages within the specified time range\n */\n getHistoryFromTimeRange(startTime: Date, endTime: Date): BaseMessage[] {\n return this._contentStorage.getMessagesFromTimeRange(startTime, endTime);\n }\n\n /**\n * Get messages from storage by message type\n * @param messageType - Type of messages to retrieve ('human', 'ai', 'system', etc.)\n * @param limit - Maximum number of messages to return\n * @returns Messages of the specified type\n */\n getHistoryByType(messageType: string, limit?: number): BaseMessage[] {\n return this._contentStorage.getMessagesByType(messageType, limit);\n }\n\n /**\n * Get recent messages from storage within the last N minutes\n * @param minutes - Number of minutes to look back\n * @returns Messages from the last N minutes\n */\n getRecentHistoryByTime(minutes: number): BaseMessage[] {\n return this._contentStorage.getRecentMessagesByTime(minutes);\n }\n\n /**\n * Export the current state for persistence or analysis\n * @returns Serializable representation of memory state\n */\n exportState(): {\n config: Required<SmartMemoryConfig>;\n activeMessages: Array<{ content: unknown; type: string }>;\n systemPrompt: string;\n memoryStats: MemoryStats;\n storageStats: ReturnType<ContentStorage['getStorageStats']>;\n storedMessages: ReturnType<ContentStorage['exportMessages']>;\n } {\n return {\n config: this.config,\n activeMessages: this.memoryWindow.getMessages().map((msg) => ({\n content: msg.content,\n type: msg._getType(),\n })),\n systemPrompt: this.memoryWindow.getSystemPrompt(),\n memoryStats: this.getMemoryStats(),\n storageStats: this.getStorageStats(),\n storedMessages: this._contentStorage.exportMessages(),\n };\n }\n\n /**\n * Get a summary of conversation context for external use\n * Useful for providing context to other systems or for logging\n * @param includeStoredContext - Whether to include recent stored messages\n * @returns Context summary object\n */\n getContextSummary(includeStoredContext: boolean = false): {\n activeMessageCount: number;\n systemPrompt: string;\n recentMessages: BaseMessage[];\n memoryUtilization: number;\n hasStoredHistory: boolean;\n recentStoredMessages?: BaseMessage[];\n storageStats?: ReturnType<ContentStorage['getStorageStats']>;\n } {\n const activeMessages = this.getMessages();\n const summary = {\n activeMessageCount: activeMessages.length,\n systemPrompt: this.getSystemPrompt(),\n recentMessages: activeMessages.slice(-5),\n memoryUtilization: this.getMemoryStats().usagePercentage,\n hasStoredHistory: this.getStorageStats().totalMessages > 0,\n };\n\n if (includeStoredContext) {\n return {\n ...summary,\n recentStoredMessages: this.getRecentHistory(10),\n storageStats: this.getStorageStats(),\n };\n }\n\n return summary;\n }\n\n /**\n * Perform maintenance operations\n * Optimizes storage and cleans up resources\n */\n performMaintenance(): void {}\n\n /**\n * Store an entity association for later resolution\n * @param entityId - The blockchain entity ID\n * @param entityName - User-provided or derived friendly name\n * @param entityType - Type of entity (token, account, topic, etc.)\n * @param transactionId - Optional transaction ID that created this entity\n */\n storeEntityAssociation(\n entityId: string,\n entityName: string,\n entityType: string,\n transactionId?: string\n ): void {\n try {\n if (\n !entityId ||\n typeof entityId !== 'string' ||\n entityId.trim().length === 0\n ) {\n return;\n }\n\n if (\n !entityName ||\n typeof entityName !== 'string' ||\n entityName.trim().length === 0\n ) {\n return;\n }\n\n if (\n !entityType ||\n typeof entityType !== 'string' ||\n entityType.trim().length === 0\n ) {\n return;\n }\n\n const sanitizedEntityId = entityId.trim();\n const sanitizedEntityName = entityName.trim().substring(0, 100);\n const sanitizedEntityType = entityType.trim().toLowerCase();\n\n const association: EntityAssociation & { isEntityAssociation: boolean } =\n {\n entityId: sanitizedEntityId,\n entityName: sanitizedEntityName,\n entityType: sanitizedEntityType,\n createdAt: new Date(),\n isEntityAssociation: true,\n ...(transactionId !== undefined &&\n transactionId !== null &&\n transactionId.trim() !== ''\n ? { transactionId: transactionId.trim() }\n : {}),\n };\n\n const content = JSON.stringify(association);\n type LangChainLikeMessage = {\n _getType: () => string;\n content: unknown;\n id: string;\n name?: string;\n additional_kwargs?: Record<string, unknown>;\n };\n\n const entityMessage: LangChainLikeMessage = {\n _getType: () => 'system',\n content: content,\n id: `entity_${sanitizedEntityId}_${Date.now()}`,\n name: 'entity_association',\n additional_kwargs: {\n entityId: sanitizedEntityId,\n entityName: sanitizedEntityName,\n entityType: sanitizedEntityType,\n isEntityAssociation: true,\n },\n };\n\n this._contentStorage.storeMessages([entityMessage as BaseMessage]);\n } catch (_error) {}\n }\n\n /**\n * Resolve entity references from natural language queries\n * @param query - Search query (entity name or natural language reference)\n * @param options - Resolution options for filtering and fuzzy matching\n * @returns Array of matching entity associations\n */\n resolveEntityReference(\n query: string,\n options: EntityResolutionOptions = {}\n ): EntityAssociation[] {\n try {\n if (!query || typeof query !== 'string') {\n return [];\n }\n\n const sanitizedQuery = query.trim();\n if (sanitizedQuery.length === 0) {\n return [];\n }\n\n if (sanitizedQuery.length > 200) {\n }\n\n const { entityType, limit = 10, fuzzyMatch = true } = options;\n\n const safeLimit = Math.max(1, Math.min(limit || 10, 100));\n\n const isEntityIdQuery = /^0\\.0\\.\\d+$/.test(sanitizedQuery);\n\n const searchResults = this._contentStorage.searchMessages(\n sanitizedQuery.substring(0, 200),\n {\n caseSensitive: false,\n limit: safeLimit * 2,\n }\n );\n\n const associations: EntityAssociation[] = [];\n\n for (const message of searchResults) {\n try {\n const content = message.content as string;\n if (\n content.includes(IS_ENTITY_ASSOCIATION_FLAG) ||\n content.includes('entityId')\n ) {\n const parsed = JSON.parse(content);\n if (parsed.entityId && parsed.entityName && parsed.entityType) {\n if (entityType && parsed.entityType !== entityType) {\n continue;\n }\n\n if (isEntityIdQuery) {\n if (parsed.entityId !== sanitizedQuery) {\n continue;\n }\n }\n\n associations.push(parsed as EntityAssociation);\n }\n }\n } catch {\n continue;\n }\n }\n\n if (fuzzyMatch && associations.length === 0 && !isEntityIdQuery) {\n const fuzzyQueries = [\n query.toLowerCase(),\n `token`,\n `account`,\n entityType || '',\n ].filter(Boolean);\n\n for (const fuzzyQuery of fuzzyQueries) {\n if (fuzzyQuery === query.toLowerCase()) continue;\n\n const fuzzyResults = this._contentStorage.searchMessages(fuzzyQuery, {\n caseSensitive: false,\n limit: limit,\n });\n\n for (const message of fuzzyResults) {\n try {\n const content = message.content as string;\n if (content.includes(IS_ENTITY_ASSOCIATION_FLAG)) {\n const parsed = JSON.parse(content);\n if (parsed.entityId && parsed.entityName && parsed.entityType) {\n if (entityType && parsed.entityType !== entityType) {\n continue;\n }\n associations.push(parsed as EntityAssociation);\n }\n }\n } catch {\n continue;\n }\n }\n }\n }\n\n const uniqueAssociations = associations\n .filter(\n (assoc, index, arr) =>\n arr.findIndex((a) => a.entityId === assoc.entityId) === index\n )\n .sort(\n (a, b) =>\n new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()\n );\n\n const results = uniqueAssociations.slice(0, safeLimit);\n\n return results;\n } catch (_error) {\n return [];\n }\n }\n\n /**\n * Get all entity associations, optionally filtered by type\n * @param entityType - Optional filter by entity type\n * @returns Array of entity associations\n */\n getEntityAssociations(entityType?: string): EntityAssociation[] {\n try {\n const sanitizedEntityType = entityType\n ? entityType.trim().toLowerCase()\n : undefined;\n\n if (\n entityType &&\n (!sanitizedEntityType || sanitizedEntityType.length === 0)\n ) {\n return [];\n }\n\n const SEARCH_ANY_ENTITY = 'entityId';\n const searchQuery = sanitizedEntityType || SEARCH_ANY_ENTITY;\n const searchResults = this._contentStorage.searchMessages(searchQuery, {\n caseSensitive: false,\n limit: 100,\n });\n\n const associations: EntityAssociation[] = [];\n\n for (const message of searchResults) {\n try {\n const content = message.content as string;\n if (content.includes(IS_ENTITY_ASSOCIATION_FLAG)) {\n const parsed = JSON.parse(content);\n\n if (parsed.entityId && parsed.entityName && parsed.entityType) {\n if (\n sanitizedEntityType &&\n parsed.entityType !== sanitizedEntityType\n ) {\n continue;\n }\n\n if (parsed.createdAt && typeof parsed.createdAt === 'string') {\n parsed.createdAt = new Date(parsed.createdAt);\n }\n\n associations.push(parsed as EntityAssociation);\n }\n }\n } catch (_parseError) {\n continue;\n }\n }\n\n const results = associations\n .filter(\n (assoc, index, arr) =>\n arr.findIndex((a) => a.entityId === assoc.entityId) === index\n )\n .sort((a, b): number => {\n const getTime = (d: Date | string): number =>\n d instanceof Date ? d.getTime() : new Date(d).getTime();\n const aTime = getTime(a.createdAt);\n const bTime = getTime(b.createdAt);\n return bTime - aTime;\n });\n\n return results;\n } catch (_error) {\n return [];\n }\n }\n\n /**\n * Clean up resources and dispose of components\n */\n dispose(): void {\n this.memoryWindow.dispose();\n this._contentStorage.dispose();\n this.tokenCounter.dispose();\n }\n}\n","import type { BaseChatModel } from '@langchain/core/language_models/chat_models';\nimport type { StructuredTool } from '@langchain/core/tools';\nimport { createOpenAIToolsAgent } from 'langchain/agents';\nimport { ContentAwareAgentExecutor } from './langchain/ContentAwareAgentExecutor';\nimport {\n ChatPromptTemplate,\n MessagesPlaceholder,\n} from '@langchain/core/prompts';\nimport { ChatOpenAI } from '@langchain/openai';\nimport {\n calculateTokenCostSync,\n getAllHederaCorePlugins,\n HederaAgentKit,\n TokenUsageCallbackHandler,\n} from 'hedera-agent-kit';\nimport type { TokenUsage, CostCalculation } from 'hedera-agent-kit';\nimport {\n BaseAgent,\n type ConversationContext,\n type ChatResponse,\n type OperationalMode,\n type UsageStats,\n} from './base-agent';\nimport { MCPClientManager } from './mcp/MCPClientManager';\nimport { convertMCPToolToLangChain } from './mcp/adapters/langchain';\nimport { SmartMemoryManager } from './memory/SmartMemoryManager';\nimport type { MCPConnectionStatus } from './mcp/types';\n\nexport class LangChainAgent extends BaseAgent {\n private executor: ContentAwareAgentExecutor | undefined;\n private systemMessage = '';\n private mcpManager?: MCPClientManager;\n private smartMemory: SmartMemoryManager | undefined;\n private mcpConnectionStatus: Map<string, MCPConnectionStatus> = new Map();\n\n async boot(): Promise<void> {\n if (this.initialized) {\n this.logger.warn('Agent already initialized');\n return;\n }\n\n try {\n this.agentKit = await this.createAgentKit();\n await this.agentKit.initialize();\n\n const modelName =\n this.config.ai?.modelName ||\n process.env.OPENAI_MODEL_NAME ||\n 'gpt-4o-mini';\n this.tokenTracker = new TokenUsageCallbackHandler(modelName);\n\n const allTools = this.agentKit.getAggregatedLangChainTools();\n this.tools = this.filterTools(allTools);\n\n if (this.config.mcp?.servers && this.config.mcp.servers.length > 0) {\n if (this.config.mcp.autoConnect !== false) {\n await this.initializeMCP();\n } else {\n this.logger.info(\n 'MCP servers configured but autoConnect=false, skipping synchronous connection'\n );\n this.mcpManager = new MCPClientManager(this.logger);\n }\n }\n\n this.smartMemory = new SmartMemoryManager({\n modelName,\n maxTokens: 90000,\n reserveTokens: 10000,\n storageLimit: 1000,\n });\n\n this.logger.info('SmartMemoryManager initialized:', {\n modelName,\n toolsCount: this.tools.length,\n maxTokens: 90000,\n reserveTokens: 10000,\n });\n\n this.systemMessage = this.buildSystemPrompt();\n\n this.smartMemory.setSystemPrompt(this.systemMessage);\n\n await this.createExecutor();\n\n this.initialized = true;\n this.logger.info('LangChain Hedera agent initialized');\n } catch (error) {\n this.logger.error('Failed to initialize agent:', error);\n throw error;\n }\n }\n\n async chat(\n message: string,\n context?: ConversationContext\n ): Promise<ChatResponse> {\n if (!this.initialized || !this.executor || !this.smartMemory) {\n throw new Error('Agent not initialized. Call boot() first.');\n }\n\n try {\n this.logger.info('LangChainAgent.chat called with:', {\n message,\n contextLength: context?.messages?.length || 0,\n });\n\n if (context?.messages && context.messages.length > 0) {\n this.smartMemory.clear();\n\n for (const msg of context.messages) {\n this.smartMemory.addMessage(msg);\n }\n }\n\n const { HumanMessage } = await import('@langchain/core/messages');\n this.smartMemory.addMessage(new HumanMessage(message));\n\n const memoryStats = this.smartMemory.getMemoryStats();\n this.logger.info('Memory stats before execution:', {\n totalMessages: memoryStats.totalActiveMessages,\n currentTokens: memoryStats.currentTokenCount,\n maxTokens: memoryStats.maxTokens,\n usagePercentage: memoryStats.usagePercentage,\n toolsCount: this.tools.length,\n });\n\n const result = await this.executor.invoke({\n input: message,\n chat_history: this.smartMemory.getMessages(),\n });\n\n this.logger.info('LangChainAgent executor result:', result);\n\n let response: ChatResponse = {\n output: result.output || '',\n message: result.output || '',\n notes: [],\n intermediateSteps: result.intermediateSteps,\n };\n\n if (result.intermediateSteps && Array.isArray(result.intermediateSteps)) {\n const toolCalls = result.intermediateSteps.map(\n (step: any, index: number) => ({\n id: `call_${index}`,\n name: step.action?.tool || 'unknown',\n args: step.action?.toolInput || {},\n output:\n typeof step.observation === 'string'\n ? step.observation\n : JSON.stringify(step.observation),\n })\n );\n\n if (toolCalls.length > 0) {\n response.tool_calls = toolCalls;\n }\n }\n\n const parsedSteps = result?.intermediateSteps?.[0]?.observation;\n if (\n parsedSteps &&\n typeof parsedSteps === 'string' &&\n this.isJSON(parsedSteps)\n ) {\n try {\n const parsed = JSON.parse(parsedSteps);\n response = { ...response, ...parsed };\n } catch (error) {\n this.logger.error('Error parsing intermediate steps:', error);\n }\n }\n\n if (!response.output || response.output.trim() === '') {\n response.output = 'Agent action complete.';\n }\n\n if (response.output) {\n const { AIMessage } = await import('@langchain/core/messages');\n this.smartMemory.addMessage(new AIMessage(response.output));\n }\n\n if (this.tokenTracker) {\n const tokenUsage = this.tokenTracker.getLatestTokenUsage();\n if (tokenUsage) {\n response.tokenUsage = tokenUsage;\n response.cost = calculateTokenCostSync(tokenUsage);\n }\n }\n\n const finalMemoryStats = this.smartMemory.getMemoryStats();\n response.metadata = {\n ...response.metadata,\n memoryStats: {\n activeMessages: finalMemoryStats.totalActiveMessages,\n tokenUsage: finalMemoryStats.currentTokenCount,\n maxTokens: finalMemoryStats.maxTokens,\n usagePercentage: finalMemoryStats.usagePercentage,\n },\n };\n\n this.logger.info('LangChainAgent.chat returning response:', response);\n return response;\n } catch (error) {\n this.logger.error('LangChainAgent.chat error:', error);\n return this.handleError(error);\n }\n }\n\n async shutdown(): Promise<void> {\n if (this.mcpManager) {\n await this.mcpManager.disconnectAll();\n }\n\n if (this.smartMemory) {\n this.smartMemory.dispose();\n this.smartMemory = undefined;\n }\n\n this.executor = undefined;\n this.agentKit = undefined;\n this.tools = [];\n this.initialized = false;\n this.logger.info('Agent cleaned up');\n }\n\n switchMode(mode: OperationalMode): void {\n if (this.config.execution) {\n this.config.execution.operationalMode = mode;\n } else {\n this.config.execution = { operationalMode: mode };\n }\n\n if (this.agentKit) {\n this.agentKit.operationalMode = mode;\n }\n\n this.systemMessage = this.buildSystemPrompt();\n this.logger.info(`Operational mode switched to: ${mode}`);\n }\n\n getUsageStats(): UsageStats {\n if (!this.tokenTracker) {\n return {\n promptTokens: 0,\n completionTokens: 0,\n totalTokens: 0,\n cost: { totalCost: 0 } as CostCalculation,\n };\n }\n\n const usage = this.tokenTracker.getTotalTokenUsage();\n const cost = calculateTokenCostSync(usage);\n return { ...usage, cost };\n }\n\n getUsageLog(): UsageStats[] {\n if (!this.tokenTracker) {\n return [];\n }\n\n return this.tokenTracker.getTokenUsageHistory().map((usage) => ({\n ...usage,\n cost: calculateTokenCostSync(usage),\n }));\n }\n\n clearUsageStats(): void {\n if (this.tokenTracker) {\n this.tokenTracker.reset();\n this.logger.info('Usage statistics cleared');\n }\n }\n\n getMCPConnectionStatus(): Map<string, MCPConnectionStatus> {\n return new Map(this.mcpConnectionStatus);\n }\n\n private async createAgentKit(): Promise<HederaAgentKit> {\n const corePlugins = getAllHederaCorePlugins();\n const extensionPlugins = this.config.extensions?.plugins || [];\n const plugins = [...corePlugins, ...extensionPlugins];\n\n const operationalMode =\n this.config.execution?.operationalMode || 'returnBytes';\n const modelName = this.config.ai?.modelName || 'gpt-4o';\n\n return new HederaAgentKit(\n this.config.signer,\n { plugins },\n operationalMode,\n this.config.execution?.userAccountId,\n this.config.execution?.scheduleUserTransactionsInBytesMode ?? false,\n undefined,\n modelName,\n this.config.extensions?.mirrorConfig,\n this.config.debug?.silent ?? false\n );\n }\n\n private async createExecutor(): Promise<void> {\n let llm: BaseChatModel;\n if (this.config.ai?.provider && this.config.ai.provider.getModel) {\n llm = this.config.ai.provider.getModel() as BaseChatModel;\n } else if (this.config.ai?.llm) {\n llm = this.config.ai.llm as BaseChatModel;\n } else {\n const apiKey = this.config.ai?.apiKey || process.env.OPENAI_API_KEY;\n if (!apiKey) {\n throw new Error('OpenAI API key required');\n }\n\n const modelName = this.config.ai?.modelName || 'gpt-4o-mini';\n const isGPT5Model =\n modelName.toLowerCase().includes('gpt-5') ||\n modelName.toLowerCase().includes('gpt5');\n\n llm = new ChatOpenAI({\n apiKey,\n modelName,\n callbacks: this.tokenTracker ? [this.tokenTracker] : [],\n ...(isGPT5Model ? { temperature: 1 } : {}),\n });\n }\n\n const prompt = ChatPromptTemplate.fromMessages([\n ['system', this.systemMessage],\n new MessagesPlaceholder('chat_history'),\n ['human', '{input}'],\n new MessagesPlaceholder('agent_scratchpad'),\n ]);\n\n const langchainTools = this.tools as unknown as StructuredTool[];\n\n const agent = await createOpenAIToolsAgent({\n llm,\n tools: langchainTools,\n prompt,\n });\n\n this.executor = new ContentAwareAgentExecutor({\n agent,\n tools: langchainTools,\n verbose: this.config.debug?.verbose ?? false,\n returnIntermediateSteps: true,\n });\n }\n\n private handleError(error: unknown): ChatResponse {\n const errorMessage =\n error instanceof Error ? error.message : 'Unknown error';\n this.logger.error('Chat error:', error);\n\n let tokenUsage: TokenUsage | undefined;\n let cost: CostCalculation | undefined;\n\n if (this.tokenTracker) {\n tokenUsage = this.tokenTracker.getLatestTokenUsage();\n if (tokenUsage) {\n cost = calculateTokenCostSync(tokenUsage);\n }\n }\n\n let userFriendlyMessage = errorMessage;\n let userFriendlyOutput = errorMessage;\n\n if (errorMessage.includes('429')) {\n if (errorMessage.includes('quota')) {\n userFriendlyMessage =\n 'API quota exceeded. Please check your OpenAI billing and usage limits.';\n userFriendlyOutput =\n \"I'm currently unable to respond because the API quota has been exceeded. Please check your OpenAI account billing and usage limits, then try again.\";\n } else {\n userFriendlyMessage =\n 'Too many requests. Please wait a moment and try again.';\n userFriendlyOutput =\n \"I'm receiving too many requests right now. Please wait a moment and try again.\";\n }\n } else if (\n errorMessage.includes('401') ||\n errorMessage.includes('unauthorized')\n ) {\n userFriendlyMessage =\n 'API authentication failed. Please check your API key configuration.';\n userFriendlyOutput =\n \"There's an issue with the API authentication. Please check your OpenAI API key configuration in settings.\";\n } else if (errorMessage.includes('timeout')) {\n userFriendlyMessage = 'Request timed out. Please try again.';\n userFriendlyOutput =\n 'The request took too long to process. Please try again.';\n } else if (\n errorMessage.includes('network') ||\n errorMessage.includes('fetch')\n ) {\n userFriendlyMessage =\n 'Network error. Please check your internet connection and try again.';\n userFriendlyOutput =\n 'There was a network error. Please check your internet connection and try again.';\n } else if (errorMessage.includes('400')) {\n userFriendlyMessage = errorMessage;\n userFriendlyOutput = errorMessage;\n }\n\n const errorResponse: ChatResponse = {\n output: userFriendlyOutput,\n message: userFriendlyMessage,\n error: errorMessage,\n notes: [],\n };\n\n if (tokenUsage) {\n errorResponse.tokenUsage = tokenUsage;\n }\n\n if (cost) {\n errorResponse.cost = cost;\n }\n\n return errorResponse;\n }\n\n private async initializeMCP(): Promise<void> {\n this.mcpManager = new MCPClientManager(this.logger);\n\n for (const serverConfig of this.config.mcp!.servers!) {\n if (serverConfig.autoConnect === false) {\n this.logger.info(\n `Skipping MCP server ${serverConfig.name} (autoConnect=false)`\n );\n continue;\n }\n\n const status = await this.mcpManager.connectServer(serverConfig);\n\n if (status.connected) {\n this.logger.info(\n `Connected to MCP server ${status.serverName} with ${status.tools.length} tools`\n );\n\n for (const mcpTool of status.tools) {\n const langchainTool = convertMCPToolToLangChain(\n mcpTool,\n this.mcpManager,\n serverConfig\n );\n this.tools.push(langchainTool);\n }\n } else {\n this.logger.error(\n `Failed to connect to MCP server ${status.serverName}: ${status.error}`\n );\n }\n }\n }\n\n /**\n * Connect to MCP servers asynchronously after agent boot with background timeout pattern\n */\n async connectMCPServers(): Promise<void> {\n if (!this.config.mcp?.servers || this.config.mcp.servers.length === 0) {\n return;\n }\n\n if (!this.mcpManager) {\n this.mcpManager = new MCPClientManager(this.logger);\n }\n\n this.logger.info(\n `Starting background MCP server connections for ${this.config.mcp.servers.length} servers...`\n );\n\n this.config.mcp.servers.forEach((serverConfig) => {\n this.connectServerInBackground(serverConfig);\n });\n\n this.logger.info('MCP server connections initiated in background');\n }\n\n /**\n * Connect to a single MCP server in background with timeout\n */\n private connectServerInBackground(serverConfig: any): void {\n const serverName = serverConfig.name;\n\n setTimeout(async () => {\n try {\n this.logger.info(`Background connecting to MCP server: ${serverName}`);\n\n const status = await this.mcpManager!.connectServer(serverConfig);\n this.mcpConnectionStatus.set(serverName, status);\n\n if (status.connected) {\n this.logger.info(\n `Successfully connected to MCP server ${status.serverName} with ${status.tools.length} tools`\n );\n\n for (const mcpTool of status.tools) {\n const langchainTool = convertMCPToolToLangChain(\n mcpTool,\n this.mcpManager!,\n serverConfig\n );\n this.tools.push(langchainTool);\n }\n\n if (this.initialized && this.executor) {\n this.logger.info(\n `Recreating executor with ${this.tools.length} total tools`\n );\n await this.createExecutor();\n }\n } else {\n this.logger.error(\n `Failed to connect to MCP server ${status.serverName}: ${status.error}`\n );\n }\n } catch (error) {\n this.logger.error(\n `Background connection failed for MCP server ${serverName}:`,\n error\n );\n\n this.mcpConnectionStatus.set(serverName, {\n connected: false,\n serverName,\n tools: [],\n error: error instanceof Error ? error.message : 'Connection failed',\n });\n }\n }, 1000);\n }\n\n /**\n * Check if a string is valid JSON\n */\n private isJSON(str: string): boolean {\n if (typeof str !== 'string') return false;\n\n const trimmed = str.trim();\n if (!trimmed) return false;\n\n if (\n !(trimmed.startsWith('{') && trimmed.endsWith('}')) &&\n !(trimmed.startsWith('[') && trimmed.endsWith(']'))\n ) {\n return false;\n }\n\n try {\n JSON.parse(trimmed);\n return true;\n } catch {\n return false;\n }\n }\n}\n","import { BaseAgent, type HederaAgentConfiguration } from './base-agent';\nimport { LangChainAgent } from './langchain-agent';\n\nexport function createAgent(\n config: HederaAgentConfiguration & {\n framework?: 'langchain' | 'vercel' | 'baml';\n }\n): BaseAgent {\n const framework = config.framework || 'langchain';\n\n switch (framework) {\n case 'langchain':\n return new LangChainAgent(config);\n case 'vercel':\n throw new Error('Vercel AI SDK support coming soon');\n case 'baml':\n throw new Error('BAML support coming soon');\n default:\n throw new Error(`Unknown framework: ${framework}`);\n }\n}","import type { \n BaseLanguageModelCallOptions\n} from '@langchain/core/language_models/base';\nimport type { BaseChatModel } from '@langchain/core/language_models/chat_models';\n\n/**\n * Framework-agnostic AI provider interface for multi-framework support\n */\nexport interface AIProvider {\n /**\n * Generate a response from the AI model\n */\n generate(\n prompt: string,\n options?: BaseLanguageModelCallOptions\n ): Promise<string>;\n\n /**\n * Stream a response from the AI model\n */\n stream?(\n prompt: string,\n options?: BaseLanguageModelCallOptions\n ): AsyncGenerator<string>;\n\n /**\n * Get the underlying model if available\n */\n getModel?(): BaseChatModel | unknown;\n}\n\n/**\n * LangChain AI provider implementation\n */\nexport class LangChainProvider implements AIProvider {\n constructor(private model: BaseChatModel) {}\n\n async generate(\n prompt: string,\n options?: BaseLanguageModelCallOptions\n ): Promise<string> {\n const result = await this.model.invoke(prompt, options);\n return typeof result === 'string' ? result : result.toString();\n }\n\n async *stream(\n prompt: string,\n options?: BaseLanguageModelCallOptions\n ): AsyncGenerator<string> {\n const stream = await this.model.stream(prompt, options);\n for await (const chunk of stream) {\n yield typeof chunk === 'string' ? chunk : chunk.toString();\n }\n }\n\n getModel(): BaseChatModel {\n return this.model;\n }\n}\n\n/**\n * Vercel AI SDK provider interface (forward-thinking)\n */\nexport interface VercelAIProvider extends AIProvider {\n /**\n * Use Vercel AI SDK's streamText function\n */\n streamText?(prompt: string, options?: unknown): Promise<unknown>;\n}\n\n/**\n * BAML provider interface (forward-thinking)\n */\nexport interface BAMLProvider extends AIProvider {\n /**\n * Execute a BAML function\n */\n executeFunction?(\n name: string,\n args: Record<string, unknown>\n ): Promise<unknown>;\n}","export const getSystemMessage = (\n accountId: string\n): string => `You are a helpful assistant managing Hashgraph Online HCS-10 connections, messages, HCS-2 registries, content inscription, and Hedera Hashgraph operations.\n\nYou have access to tools for:\n- HCS-10: registering agents, finding registered agents, initiating connections, listing active connections, sending messages over connections, and checking for new messages\n- HCS-2: creating registries, registering entries, updating entries, deleting entries, migrating registries, and querying registry contents\n- Inscription: inscribing content from URLs, files, or buffers, creating Hashinal NFTs, and retrieving inscriptions\n- Hedera Token Service (HTS): creating tokens, transferring tokens, airdropping tokens, and managing token operations\n\n*** IMPORTANT CONTEXT ***\nYou are currently operating as agent: ${accountId} on the Hashgraph Online network\nWhen users ask about \"my profile\", \"my account\", \"my connections\", etc., use this account ID: ${accountId}\n\n*** CRITICAL ENTITY HANDLING RULES ***\n- When users refer to entities (tokens, topics, accounts) with pronouns like \"it\", \"that\", \"the token/topic\", etc., ALWAYS use the most recently created entity of that type\n- Entity IDs look like \"0.0.XXXXXX\" and are stored in memory after creation\n- NEVER use example or placeholder IDs like \"0.0.123456\" - always use actual created entity IDs\n- Account ID ${accountId} is NOT a token - tokens and accounts are different entities\n\nRemember the connection numbers when listing connections, as users might refer to them.`;\n","import { ContentStorage } from '../memory/ContentStorage';\nimport { \n ContentStoreService, \n extractReferenceId, \n shouldUseReference,\n ContentResolverRegistry,\n type ContentStoreInterface, \n type ContentResolverInterface, \n type ReferenceResolutionResult \n} from '@hashgraphonline/standards-sdk';\nimport type { ContentReferenceConfig } from '../types/content-reference';\nimport { Logger } from '@hashgraphonline/standards-sdk';\n\n/**\n * Adapter to make ContentStorage compatible with ContentStoreInterface\n */\nclass ContentStorageAdapter implements ContentStoreInterface {\n constructor(private storage: ContentStorage) {}\n\n async storeContent(content: Buffer, metadata: any) {\n const contentRef = await this.storage.storeContent(content, metadata);\n return contentRef.referenceId;\n }\n\n async resolveReference(referenceId: string): Promise<ReferenceResolutionResult> {\n const result = await this.storage.resolveReference(referenceId);\n if (result.success && result.content) {\n const response: ReferenceResolutionResult = {\n content: result.content\n };\n if (result.metadata) {\n response.metadata = {\n ...(result.metadata.mimeType !== undefined && { mimeType: result.metadata.mimeType }),\n ...(result.metadata.fileName !== undefined && { fileName: result.metadata.fileName }),\n originalSize: result.metadata.sizeBytes\n };\n }\n return response;\n } else {\n throw new Error(result.error || 'Reference not found');\n }\n }\n\n async hasReference(referenceId: string) {\n return await this.storage.hasReference(referenceId);\n }\n\n async cleanupReference(referenceId: string) {\n await this.storage.cleanupReference(referenceId);\n }\n\n async getStats() {\n return await this.storage.getStats();\n }\n\n async updateConfig(config: any) {\n return await this.storage.updateConfig(config);\n }\n\n async performCleanup() {\n await this.storage.performCleanup();\n }\n\n async dispose() {\n return Promise.resolve(this.storage.dispose());\n }\n}\n\n/**\n * Content resolver implementation for dependency injection\n */\nclass ContentResolver implements ContentResolverInterface {\n constructor(private adapter: ContentStorageAdapter) {}\n\n async resolveReference(referenceId: string): Promise<ReferenceResolutionResult> {\n return await this.adapter.resolveReference(referenceId);\n }\n\n shouldUseReference(content: string | Buffer): boolean {\n return shouldUseReference(content);\n }\n\n extractReferenceId(input: string): string | null {\n return extractReferenceId(input);\n }\n}\n\n/**\n * Manages content store lifecycle and cross-package registration\n */\nexport class ContentStoreManager {\n private contentStorage: ContentStorage;\n private adapter: ContentStorageAdapter;\n private resolver: ContentResolver;\n private logger: Logger;\n private isRegistered = false;\n\n constructor(\n maxMessageStorage: number = 1000,\n referenceConfig?: Partial<ContentReferenceConfig>,\n logger?: Logger\n ) {\n this.logger = logger || {\n info: console.log,\n debug: console.log,\n warn: console.warn,\n error: console.error\n } as Logger;\n\n this.contentStorage = new ContentStorage(maxMessageStorage, referenceConfig);\n this.adapter = new ContentStorageAdapter(this.contentStorage);\n this.resolver = new ContentResolver(this.adapter);\n }\n\n /**\n * Initialize and register content storage for cross-package access\n */\n async initialize(): Promise<void> {\n if (this.isRegistered) {\n this.logger.warn('ContentStoreManager is already initialized');\n return;\n }\n\n try {\n await ContentStoreService.setInstance(this.adapter);\n ContentResolverRegistry.register(this.resolver);\n this.isRegistered = true;\n this.logger.info('ContentStoreManager initialized and registered for cross-package access');\n } catch (error) {\n this.logger.error('Failed to initialize ContentStoreManager:', error);\n throw error;\n }\n }\n\n /**\n * Get the underlying ContentStorage instance\n */\n getContentStorage(): ContentStorage {\n return this.contentStorage;\n }\n\n /**\n * Get storage statistics\n */\n async getStats() {\n return await this.contentStorage.getStats();\n }\n\n /**\n * Update configuration\n */\n async updateConfig(config: Partial<ContentReferenceConfig>) {\n return await this.contentStorage.updateConfig(config);\n }\n\n /**\n * Perform manual cleanup\n */\n async performCleanup() {\n return await this.contentStorage.performCleanup();\n }\n\n /**\n * Check if content should be stored as reference\n */\n shouldUseReference(content: Buffer | string): boolean {\n return this.contentStorage.shouldUseReference(content);\n }\n\n /**\n * Store content if it's large enough\n */\n async storeContentIfLarge(content: Buffer | string, metadata: any) {\n return await this.contentStorage.storeContentIfLarge(content, metadata);\n }\n\n /**\n * Cleanup and unregister\n */\n async dispose(): Promise<void> {\n if (this.isRegistered) {\n this.contentStorage.dispose();\n ContentStoreService.dispose();\n ContentResolverRegistry.unregister();\n this.isRegistered = false;\n this.logger.info('ContentStoreManager disposed and unregistered');\n }\n }\n\n /**\n * Check if the manager is initialized\n */\n isInitialized(): boolean {\n return this.isRegistered;\n }\n}","import { StructuredTool } from '@langchain/core/tools';\nimport { z } from 'zod';\nimport { ChatOpenAI } from '@langchain/openai';\nimport type { EntityAssociation } from '../memory/SmartMemoryManager';\n\nconst ResolveEntitiesSchema = z.object({\n message: z.string().describe('The message containing entity references to resolve'),\n entities: z.array(z.object({\n entityId: z.string(),\n entityName: z.string(),\n entityType: z.string(),\n })).describe('Available entities in memory'),\n});\n\nconst ExtractEntitiesSchema = z.object({\n response: z.string().describe('Agent response text to extract entities from'),\n userMessage: z.string().describe('Original user message for context'),\n});\n\nexport class ResolveEntitiesTool extends StructuredTool {\n name = 'resolve_entities';\n description = 'Resolves entity references like \"the topic\", \"it\", \"that\" to actual entity IDs';\n schema = ResolveEntitiesSchema;\n \n private llm: ChatOpenAI;\n \n constructor(apiKey: string, modelName = 'gpt-4o-mini') {\n super();\n this.llm = new ChatOpenAI({\n apiKey,\n modelName,\n temperature: 0,\n });\n }\n \n async _call(input: z.infer<typeof ResolveEntitiesSchema>): Promise<string> {\n const { message, entities } = input;\n \n if (!entities || entities.length === 0) {\n return message;\n }\n \n const byType = this.groupEntitiesByType(entities);\n const context = this.buildEntityContext(byType);\n \n const prompt = `Task: Replace entity references with IDs.\n\n${context}\n\nMessage: \"${message}\"\n\nRules:\n- \"the topic\" or \"that topic\" → replace with most recent topic ID\n- \"the token\" or \"that token\" → replace with most recent token ID\n- \"it\" or \"that\" after action verb → replace with most recent entity ID\n- \"airdrop X\" without token ID → add most recent token ID as first parameter\n- Token operations without explicit token → use most recent token ID\n\nExamples:\n- \"submit on the topic\" → \"submit on 0.0.6543472\"\n- \"airdrop the token\" → \"airdrop 0.0.123456\"\n- \"airdrop 10 to 0.0.5842697\" → \"airdrop 0.0.123456 10 to 0.0.5842697\"\n- \"mint 100\" → \"mint 0.0.123456 100\"\n\nReturn ONLY the resolved message:`;\n \n try {\n const response = await this.llm.invoke(prompt);\n return (response.content as string).trim();\n } catch (error) {\n console.error('[ResolveEntitiesTool] Failed:', error);\n return message;\n }\n }\n \n private groupEntitiesByType(entities: EntityGroup): GroupedEntities {\n return entities.reduce((acc, entity) => {\n if (!acc[entity.entityType]) {\n acc[entity.entityType] = [];\n }\n acc[entity.entityType].push(entity);\n return acc;\n }, {} as GroupedEntities);\n }\n \n private buildEntityContext(groupedEntities: GroupedEntities): string {\n let context = 'Available entities:\\n';\n for (const [type, list] of Object.entries(groupedEntities)) {\n const recent = list[0];\n context += `- Most recent ${type}: \"${recent.entityName}\" = ${recent.entityId}\\n`;\n }\n return context;\n }\n}\n\nexport class ExtractEntitiesTool extends StructuredTool {\n name = 'extract_entities';\n description = 'Extracts newly created entities from agent responses';\n schema = ExtractEntitiesSchema;\n \n private llm: ChatOpenAI;\n \n constructor(apiKey: string, modelName = 'gpt-4o-mini') {\n super();\n this.llm = new ChatOpenAI({\n apiKey,\n modelName,\n temperature: 0,\n });\n }\n \n async _call(input: z.infer<typeof ExtractEntitiesSchema>): Promise<string> {\n const { response, userMessage } = input;\n \n const prompt = `Extract ONLY newly created entities from this response.\n\nUser asked: \"${userMessage.substring(0, 200)}\"\nResponse: ${response.substring(0, 3000)}\n\nLook for:\n- Success messages with new entity IDs\n- Words like \"created\", \"new\", \"successfully\" followed by entity IDs\n\nReturn JSON array of created entities:\n[{\"id\": \"0.0.XXX\", \"name\": \"name\", \"type\": \"topic|token|account\"}]\n\nIf none created, return: []\n\nJSON:`;\n \n try {\n const llmResponse = await this.llm.invoke(prompt);\n const content = llmResponse.content as string;\n const match = content.match(/\\[[\\s\\S]*?\\]/);\n if (match) {\n return match[0];\n }\n return '[]';\n } catch (error) {\n console.error('[ExtractEntitiesTool] Failed:', error);\n return '[]';\n }\n }\n}\n\nexport function createEntityTools(apiKey: string, modelName = 'gpt-4o-mini'): {\n resolveEntities: ResolveEntitiesTool;\n extractEntities: ExtractEntitiesTool;\n} {\n return {\n resolveEntities: new ResolveEntitiesTool(apiKey, modelName),\n extractEntities: new ExtractEntitiesTool(apiKey, modelName),\n };\n}\n\ninterface EntityReference {\n entityId: string;\n entityName: string;\n entityType: string;\n}\n\ntype EntityGroup = EntityReference[];\n\ntype GroupedEntities = Record<string, EntityGroup>;\n\ninterface ExtractedEntity {\n id: string;\n name: string;\n type: string;\n}","import {\n ServerSigner,\n getAllHederaCorePlugins,\n BasePlugin,\n} from 'hedera-agent-kit';\nimport {\n HederaMirrorNode,\n Logger,\n type NetworkType,\n} 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 { HumanMessage, AIMessage } 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 { PrivateKey } from '@hashgraph/sdk';\nimport { getSystemMessage } from './config/system-message';\nimport type { MCPServerConfig, MCPConnectionStatus } from './mcp/types';\nimport { ContentStoreManager } from './services/ContentStoreManager';\nimport { SmartMemoryManager, type SmartMemoryConfig } from './memory';\nimport {\n createEntityTools,\n ResolveEntitiesTool,\n ExtractEntitiesTool,\n} from './tools/EntityResolverTool';\n\nexport type ToolDescriptor = {\n name: string;\n namespace?: string;\n};\n\nexport type ChatHistoryItem = {\n type: 'human' | 'ai';\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 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 \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 const allPlugins = this.preparePlugins();\n const agentConfig = this.createAgentConfig(serverSigner, llm, allPlugins);\n\n this.agent = createAgent(agentConfig);\n\n this.configureHCS10Plugin(allPlugins);\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 await this.agent.boot();\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('Agent not initialized. Call initialize() first.');\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 = this.memoryManager\n ? await this.resolveEntitiesInMessage(message)\n : message;\n\n const messages = chatHistory.map((msg) => {\n if (msg.type === 'human') {\n return new HumanMessage(msg.content);\n } else {\n return new AIMessage(msg.content);\n }\n });\n\n const context: ConversationContext = {\n messages,\n };\n\n const response = await this.agent.chat(resolvedMessage, context);\n\n if (this.memoryManager) {\n await this.extractAndStoreEntities(response, message);\n }\n\n this.logger.info('Message processed successfully');\n\n return response;\n } catch (error) {\n this.logger.error('Error processing message:', 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(`Account ID must be a string, received ${typeof accountId}`);\n }\n \n if (typeof privateKey !== 'string') {\n throw new Error(`Private key must be a string, received ${typeof privateKey}: ${JSON.stringify(privateKey)}`);\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 /**\n * Resolve entity references using LLM-based resolver\n * @param content - Message content to resolve\n * @returns Resolved message content with entity IDs replaced\n */\n private async resolveEntitiesInMessage(content: string): Promise<string> {\n if (!this.memoryManager || !this.entityTools) {\n return content;\n }\n\n try {\n const entities = this.memoryManager.getEntityAssociations();\n\n if (entities.length === 0) {\n this.logger.info('No entities in memory, skipping resolution');\n return content;\n }\n\n this.logger.info(\n `Starting LLM-based entity resolution for: \"${content.substring(\n 0,\n 100\n )}...\"`\n );\n\n const resolvedContent = await this.entityTools.resolveEntities.call({\n message: content,\n entities: entities.map((e) => ({\n entityId: e.entityId,\n entityName: e.entityName,\n entityType: e.entityType,\n })),\n });\n\n if (resolvedContent !== content) {\n this.logger.info(\n `Entity resolution completed. Original: \"${content}\" -> Resolved: \"${resolvedContent}\"`\n );\n }\n\n return resolvedContent;\n } catch (error) {\n this.logger.error('Entity resolution failed:', error);\n throw error;\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 this.logger.info(\n `Storing entity: ${entity.name} (${entity.type}) -> ${entity.id}`\n );\n\n const transactionId = this.extractTransactionId(response);\n this.memoryManager.storeEntityAssociation(\n entity.id,\n entity.name,\n entity.type,\n transactionId\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 return (response as { transactionId?: string }).transactionId;\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 return String(response.output);\n }\n\n return JSON.stringify(response);\n }\n}\n","import type { MCPServerConfig } from './types';\n\n/**\n * Common MCP server configurations for easy setup\n */\nexport const MCPServers = {\n /**\n * Filesystem server for file operations\n */\n filesystem: (path: string): MCPServerConfig => ({\n name: 'filesystem',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-filesystem', path],\n transport: 'stdio',\n autoConnect: true,\n additionalContext: 'This server provides access to files and directories in the current working directory.',\n toolDescriptions: {\n list_directory: 'Use this tool when users ask about files in the \"current directory\" or \"working directory\".',\n read_file: 'Use this tool when users ask to see or check files in the current directory.',\n },\n }),\n\n /**\n * GitHub server for repository operations\n */\n github: (token?: string): MCPServerConfig => ({\n name: 'github',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-github'],\n ...(token && { env: { GITHUB_TOKEN: token } }),\n transport: 'stdio',\n autoConnect: true,\n }),\n\n /**\n * Slack server for messaging operations\n */\n slack: (token: string): MCPServerConfig => ({\n name: 'slack',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-slack'],\n env: { SLACK_TOKEN: token },\n transport: 'stdio',\n autoConnect: true,\n }),\n\n /**\n * Google Drive server for document operations\n */\n googleDrive: (credentials: string): MCPServerConfig => ({\n name: 'google-drive',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-google-drive'],\n env: { GOOGLE_CREDENTIALS: credentials },\n transport: 'stdio',\n autoConnect: true,\n }),\n\n /**\n * PostgreSQL server for database operations\n */\n postgres: (connectionString: string): MCPServerConfig => ({\n name: 'postgres',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-postgres', connectionString],\n transport: 'stdio',\n autoConnect: true,\n }),\n\n /**\n * SQLite server for database operations\n */\n sqlite: (dbPath: string): MCPServerConfig => ({\n name: 'sqlite',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-sqlite', dbPath],\n transport: 'stdio',\n autoConnect: true,\n }),\n\n /**\n * Custom server configuration\n */\n custom: (config: MCPServerConfig): MCPServerConfig => config,\n};\n\n/**\n * Validate MCP server configuration\n */\nexport function validateServerConfig(config: MCPServerConfig): string[] {\n const errors: string[] = [];\n\n if (!config.name) {\n errors.push('Server name is required');\n }\n\n if (!config.command) {\n errors.push('Server command is required');\n }\n\n if (!config.args || !Array.isArray(config.args)) {\n errors.push('Server args must be an array');\n }\n\n if (config.transport && !['stdio', 'http', 'websocket'].includes(config.transport)) {\n errors.push('Invalid transport type. Must be stdio, http, or websocket');\n }\n\n return errors;\n}\n\n/**\n * Create a typed MCP configuration for ConversationalAgent\n */\nexport function createMCPConfig(servers: MCPServerConfig[], autoConnect = true): { mcpServers: MCPServerConfig[] } {\n return {\n mcpServers: servers.map(server => ({\n ...server,\n autoConnect: server.autoConnect ?? autoConnect,\n })),\n };\n}"],"names":["HCS10Plugin","BasePlugin","constructor","super","arguments","this","id","name","description","version","author","namespace","tools","initialize","context","hederaKit","config","stateManager","appConfig","OpenConvaiState","accountId","signer","getAccountId","toString","inboundTopicId","outboundTopicId","opKey","getOperatorPrivateKey","privateKey","toStringRaw","String","hcs10Client","HCS10Client","network","operatorId","operatorPrivateKey","logLevel","profileResponse","retrieveProfile","success","topicInfo","inboundTopic","outboundTopic","profileError","logger","warn","setCurrentAgent","info","getConnectionsManager","initializeConnectionsManager","cmError","initializeTools","error","Error","hcs10Builder","HCS10Builder","RegisterAgentTool","FindRegistrationsTool","RetrieveProfileTool","InitiateConnectionTool","ListConnectionsTool","SendMessageToConnectionTool","CheckMessagesTool","ConnectionMonitorTool","ManageConnectionRequestsTool","AcceptConnectionRequestTool","ListUnapprovedConnectionRequestsTool","getTools","getStateManager","cleanup","HCS2Plugin","hcs2Builder","HCS2Builder","CreateRegistryTool","RegisterEntryTool","UpdateEntryTool","DeleteEntryTool","MigrateRegistryTool","QueryRegistryTool","InscribePlugin","inscriberBuilder","InscriberBuilder","InscribeFromUrlTool","InscribeFromFileTool","InscribeFromBufferTool","InscribeHashinalTool","RetrieveInscriptionTool","AccountBuilder","BaseServiceBuilder","transferHbar","params","isUserInitiated","clearNotes","transaction","TransferTransaction","transfers","length","netZeroInTinybars","BigNumber","userTransferProcessedForScheduling","kit","userAccountId","operationalMode","receiverTransfer","amountValue","amount","amountBigNum","isPositive","recipientAccountId","AccountId","fromString","roundedAmount","toFixed","ROUND_DOWN","sdkHbarAmount","Hbar","addNote","addHbarTransfer","negated","processedTransfers","transferInput","push","hbar","tinybarsContribution","toTinybars","plus","isZero","lastTransfer","adjustment","dividedBy","adjustedRounded","transfer","memo","setTransactionMemo","setCurrentTransaction","HbarTransferInputSchema","z","object","string","describe","union","number","TransferHbarZodSchemaCore","array","min","optional","TransferHbarTool","BaseHederaTransactionTool","specificInputSchema","getServiceBuilder","callBuilderMethod","builder","specificArgs","AirdropToolWrapper","StructuredTool","originalTool","agentKit","schema","tokenId","recipients","Logger","module","_call","input","decimals","getTokenInfo","convertedRecipients","map","recipient","humanAmount","parseFloat","smallestUnitAmount","convertToSmallestUnits","convertedInput","Math","floor","pow","queryTokenInfo","mirrorNode","tokenData","parseInt","mirrorNodeUrl","response","fetch","ok","json","HbarPlugin","originalAirdropTool","airdropTool","HederaAirdropTokenTool","wrappedAirdropTool","shutdown","ContentAwareAgentExecutor","AgentExecutor","BaseAgent","initialized","silent","debug","getCore","filterTools","filtered","filter","filtering","namespaceWhitelist","tool","includes","toolBlacklist","toolPredicate","buildSystemPrompt","parts","userAccId","execution","messaging","systemPreamble","scheduleUserTransactionsInBytesMode","conciseMode","systemPostamble","join","isReady","MCPContentProcessor","contentStorage","analyzeResponse","contents","totalSize","extractContentFromResponse","reduce","sum","content","sizeBytes","largestContentSize","max","shouldProcess","some","shouldUseReference","JSON","stringify","processResponse","serverName","toolName","analysis","wasProcessed","createReferencedResponse","errors","message","obj","Array","isArray","forEach","item","record","type","text","globalThis","Buffer","byteLength","mimeType","detectMimeType","data","ceil","resource","resourceStr","Object","values","value","originalResponse","processedResponse","deepClone","referenceCreated","totalReferenceSize","contentInfo","contentBuffer","from","metadata","contentType","mapMimeTypeToContentType","source","mcpToolName","tags","reference","storeContentIfLarge","replaceContentInResponse","createLightweightReference","result","originalSize","referenceId","preview","size","format","_isReference","oldContent","newContent","i","key","keys","trim","startsWith","Date","getTime","cloned","hasOwnProperty","MCPClientManager","clients","Map","contentProcessor","connectServer","isServerConnected","connected","transport","StdioClientTransport","command","args","env","client","Client","capabilities","connect","set","toolsWithServer","listTools","executeTool","get","callTool","processed","disconnectAll","close","clear","getAllTools","allTools","getServerTools","has","getConnectedServers","enableContentProcessing","disableContentProcessing","isContentProcessingEnabled","analyzeResponseContent","convertMCPToolToLangChain","mcpManager","serverConfig","zodSchema","jsonSchemaToZod","inputSchema","sanitizedName","replace","toolDescriptions","additionalContext","DynamicStructuredTool","func","async","responseText","responseBuffer","MCP_REFERENCE_THRESHOLD","contentStore","ContentStoreService","getInstance","storeContent","storeError","errorMessage","schemaObj","convertType","properties","shape","entries","zodType","required","unknown","enum","minimum","maximum","int","boolean","items","passthrough","_TokenCounter","modelName","encoding","encoding_for_model","countTokens","encode","split","countMessageTokens","getMessageRole","MESSAGE_OVERHEAD","ROLE_OVERHEAD","countMessagesTokens","messages","total","estimateSystemPromptTokens","systemPrompt","estimateContextSize","_getType","getModelName","dispose","free","TokenCounter","_MemoryWindow","maxTokens","DEFAULT_MAX_TOKENS","reserveTokens","DEFAULT_RESERVE_TOKENS","tokenCounter","systemPromptTokens","addMessage","prunedMessages","getCurrentTokenCount","pop","pruneToFit","added","currentTokenCount","remainingCapacity","getRemainingTokenCapacity","targetTokens","batchSize","PRUNING_BATCH_SIZE","prunedMessage","shift","messageTokens","canAddMessage","wouldExceedReserve","getMessages","setSystemPrompt","getSystemPrompt","getConfig","currentTokens","messageCount","updateLimits","getStats","capacity","usagePercentage","totalMessages","round","canAcceptMore","MemoryWindow","ReferenceIdGenerator","generateId","hash","createHash","update","digest","isValidReferenceId","test","extractReferenceId","refFormatMatch","match","formatReference","generateTestId","testSeed","now","DEFAULT_CONTENT_REFERENCE_CONFIG","sizeThresholdBytes","maxAgeMs","maxReferences","maxTotalStorageBytes","enableAutoCleanup","cleanupIntervalMs","enablePersistence","storageBackend","cleanupPolicies","recent","priority","userContent","agentGenerated","default","ContentReferenceError","suggestedActions","_ContentStorage","maxStorage","DEFAULT_MAX_STORAGE","referenceConfig","idCounter","referenceStats","activeReferences","totalStorageBytes","recentlyCleanedUp","totalResolutions","failedResolutions","averageContentSize","storageUtilization","performanceMetrics","averageCreationTimeMs","averageResolutionTimeMs","averageCleanupTimeMs","creationTimes","resolutionTimes","cleanupTimes","startReferenceCleanupTimer","storeMessages","stored","dropped","storedMessages","storedAt","getRecentMessages","count","startIndex","slice","searchMessages","query","options","caseSensitive","limit","useRegex","matches","regex","RegExp","searchTerm","toLowerCase","getMessagesFromTimeRange","startTime","endTime","getStorageStats","oldestMessageTime","newestMessageTime","maxStorageLimit","getTotalStoredMessages","updateStorageLimit","newLimit","getMessagesByType","messageType","currentUsage","utilizationPercentage","getRecentMessagesByTime","minutes","cutoffTime","exportMessages","toISOString","isBuffer","buffer","storeMetadata","detectContentType","fileName","customMetadata","fullMetadata","createdAt","lastAccessedAt","accessCount","storedContent","state","expirationTime","calculateExpirationTime","expiresAt","updateStatsAfterStore","enforceReferenceStorageLimits","createContentPreview","referenceMetadata","duration","recordPerformanceMetric","resolveReference","errorType","hasReference","cleanupReference","delete","updateReferenceStorageStats","calculateAverage","updateConfig","cleanupTimer","clearInterval","performCleanup","cleanedUp","toCleanup","shouldCleanup","ageMs","getCleanupPolicy","sort","a","b","aContent","bContent","aPriority","sortedByAge","excessCount","getReferenceConfig","policy","contentStr","maxLength","parsed","parse","substring","mostAccessedId","maxAccess","mostAccessedReferenceId","timeMs","metrics","times","time","setInterval","ContentStorage","IS_ENTITY_ASSOCIATION_FLAG","_SmartMemoryManager","DEFAULT_CONFIG","_contentStorage","storageLimit","memoryWindow","clearStorage","searchHistory","getRecentHistory","getMemoryStats","windowStats","totalActiveMessages","getOverallStats","memoryStats","storageStats","activeMemory","storage","totalMessagesManaged","activeMemoryUtilization","newConfig","getHistoryFromTimeRange","getHistoryByType","getRecentHistoryByTime","exportState","activeMessages","msg","getContextSummary","includeStoredContext","summary","activeMessageCount","recentMessages","memoryUtilization","hasStoredHistory","recentStoredMessages","performMaintenance","storeEntityAssociation","entityId","entityName","entityType","transactionId","sanitizedEntityId","sanitizedEntityName","sanitizedEntityType","association","isEntityAssociation","entityMessage","additional_kwargs","_error","resolveEntityReference","sanitizedQuery","fuzzyMatch","safeLimit","isEntityIdQuery","searchResults","associations","fuzzyQueries","Boolean","fuzzyQuery","fuzzyResults","uniqueAssociations","assoc","index","arr","findIndex","getEntityAssociations","searchQuery","_parseError","d","aTime","SmartMemoryManager","LangChainAgent","systemMessage","mcpConnectionStatus","boot","createAgentKit","ai","process","OPENAI_MODEL_NAME","tokenTracker","TokenUsageCallbackHandler","getAggregatedLangChainTools","mcp","servers","autoConnect","initializeMCP","smartMemory","toolsCount","createExecutor","chat","executor","contextLength","HumanMessage","import","invoke","chat_history","output","notes","intermediateSteps","toolCalls","step","action","toolInput","observation","tool_calls","parsedSteps","isJSON","AIMessage","tokenUsage","getLatestTokenUsage","cost","calculateTokenCostSync","finalMemoryStats","handleError","switchMode","mode","getUsageStats","promptTokens","completionTokens","totalTokens","totalCost","usage","getTotalTokenUsage","getUsageLog","getTokenUsageHistory","clearUsageStats","reset","getMCPConnectionStatus","plugins","getAllHederaCorePlugins","extensions","HederaAgentKit","mirrorConfig","llm","provider","getModel","apiKey","OPENAI_API_KEY","isGPT5Model","ChatOpenAI","callbacks","temperature","prompt","ChatPromptTemplate","fromMessages","MessagesPlaceholder","langchainTools","agent","createOpenAIToolsAgent","verbose","returnIntermediateSteps","userFriendlyMessage","userFriendlyOutput","errorResponse","status","mcpTool","langchainTool","connectMCPServers","connectServerInBackground","setTimeout","str","trimmed","endsWith","createAgent","framework","LangChainProvider","model","generate","stream","chunk","getSystemMessage","ContentStorageAdapter","Promise","resolve","ContentResolver","adapter","ContentStoreManager","maxMessageStorage","isRegistered","console","log","resolver","setInstance","ContentResolverRegistry","register","getContentStorage","unregister","isInitialized","ResolveEntitiesSchema","entities","ExtractEntitiesSchema","userMessage","ResolveEntitiesTool","byType","groupEntitiesByType","buildEntityContext","acc","entity","groupedEntities","list","ExtractEntitiesTool","llmResponse","createEntityTools","resolveEntities","extractEntities","DEFAULT_MODEL_NAME","DEFAULT_NETWORK","DEFAULT_OPERATIONAL_MODE","ConversationalAgent","hcs10Plugin","hcs2Plugin","inscribePlugin","hbarPlugin","disableLogging","entityMemoryEnabled","openAIApiKey","memoryManager","entityMemoryConfig","entityTools","openAIModelName","llmProvider","validateOptions","serverSigner","ServerSigner","ChatAnthropic","allPlugins","preparePlugins","agentConfig","createAgentConfig","configureHCS10Plugin","contentStoreManager","cfg","originalPredicate","userPredicate","toolFilter","mcpServers","connectMCP","getPlugin","getAgent","getConversationalAgent","processMessage","chatHistory","resolvedMessage","resolveEntitiesInMessage","extractAndStoreEntities","additionalPlugins","enabledPlugins","standardPlugins","corePlugins","enabledSet","Set","plugin","customSystemMessagePreamble","customSystemMessagePostamble","mirrorNodeConfig","scheduleUserTransactions","hcs10","find","p","withPlugins","withHTS","withHCS2","withHCS10","withInscribe","withAccount","withFileService","withConsensusService","withSmartContract","withAllStandards","minimal","withMCP","resolvedContent","call","e","originalMessage","extractResponseText","entitiesJson","extractTransactionId","parseError","catch","then","isMCPServerConnected","filesystem","path","list_directory","read_file","github","token","GITHUB_TOKEN","slack","SLACK_TOKEN","googleDrive","credentials","GOOGLE_CREDENTIALS","postgres","connectionString","sqlite","dbPath","custom","server"],"mappings":"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"}