@hashgraphonline/standards-agent-kit 0.0.37 → 0.0.38
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.
- package/dist/cjs/standards-agent-kit.cjs.map +1 -1
- package/dist/cjs/tools/AcceptConnectionRequestTool.d.ts +6 -6
- package/dist/cjs/tools/CheckMessagesTool.d.ts +6 -6
- package/dist/cjs/tools/ConnectionMonitorTool.d.ts +34 -34
- package/dist/cjs/tools/FindRegistrationsTool.d.ts +4 -4
- package/dist/cjs/tools/InitiateConnectionTool.d.ts +2 -2
- package/dist/cjs/tools/ListConnectionsTool.d.ts +4 -4
- package/dist/cjs/tools/ListUnapprovedConnectionRequestsTool.d.ts +4 -4
- package/dist/cjs/tools/ManageConnectionRequestsTool.d.ts +4 -4
- package/dist/cjs/tools/RegisterAgentTool.d.ts +76 -76
- package/dist/cjs/tools/RetrieveProfileTool.d.ts +4 -4
- package/dist/cjs/tools/SendMessageToConnectionTool.d.ts +6 -6
- package/dist/cjs/tools/SendMessageTool.d.ts +6 -6
- package/dist/es/standards-agent-kit.es14.js.map +1 -1
- package/dist/es/standards-agent-kit.es18.js.map +1 -1
- package/dist/es/standards-agent-kit.es7.js.map +1 -1
- package/dist/es/standards-agent-kit.es9.js.map +1 -1
- package/dist/es/tools/AcceptConnectionRequestTool.d.ts +6 -6
- package/dist/es/tools/CheckMessagesTool.d.ts +6 -6
- package/dist/es/tools/ConnectionMonitorTool.d.ts +34 -34
- package/dist/es/tools/FindRegistrationsTool.d.ts +4 -4
- package/dist/es/tools/InitiateConnectionTool.d.ts +2 -2
- package/dist/es/tools/ListConnectionsTool.d.ts +4 -4
- package/dist/es/tools/ListUnapprovedConnectionRequestsTool.d.ts +4 -4
- package/dist/es/tools/ManageConnectionRequestsTool.d.ts +4 -4
- package/dist/es/tools/RegisterAgentTool.d.ts +76 -76
- package/dist/es/tools/RetrieveProfileTool.d.ts +4 -4
- package/dist/es/tools/SendMessageToConnectionTool.d.ts +6 -6
- package/dist/es/tools/SendMessageTool.d.ts +6 -6
- package/dist/umd/standards-agent-kit.umd.js +49 -19
- package/dist/umd/standards-agent-kit.umd.js.map +1 -1
- package/dist/umd/tools/AcceptConnectionRequestTool.d.ts +6 -6
- package/dist/umd/tools/CheckMessagesTool.d.ts +6 -6
- package/dist/umd/tools/ConnectionMonitorTool.d.ts +34 -34
- package/dist/umd/tools/FindRegistrationsTool.d.ts +4 -4
- package/dist/umd/tools/InitiateConnectionTool.d.ts +2 -2
- package/dist/umd/tools/ListConnectionsTool.d.ts +4 -4
- package/dist/umd/tools/ListUnapprovedConnectionRequestsTool.d.ts +4 -4
- package/dist/umd/tools/ManageConnectionRequestsTool.d.ts +4 -4
- package/dist/umd/tools/RegisterAgentTool.d.ts +76 -76
- package/dist/umd/tools/RetrieveProfileTool.d.ts +4 -4
- package/dist/umd/tools/SendMessageToConnectionTool.d.ts +6 -6
- package/dist/umd/tools/SendMessageTool.d.ts +6 -6
- package/package.json +3 -6
- package/src/agents/index.ts +1 -1
- package/src/plugins/PluginRegistry.ts +11 -11
- package/src/plugins/defi/index.ts +18 -18
- package/src/tools/CheckMessagesTool.ts +1 -1
- package/src/tools/InitiateConnectionTool.ts +1 -1
- package/src/tools/RetrieveProfileTool.ts +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"standards-agent-kit.cjs","sources":["../../src/hcs10/HCS10Client.ts","../../src/tools/RegisterAgentTool.ts","../../src/utils/ensure-agent-has-hbar.ts","../../src/tools/SendMessageTool.ts","../../src/tools/ConnectionTool.ts","../../src/tools/SendMessageToConnectionTool.ts","../../src/tools/InitiateConnectionTool.ts","../../src/tools/ListConnectionsTool.ts","../../src/tools/CheckMessagesTool.ts","../../src/tools/FindRegistrationsTool.ts","../../src/tools/ConnectionMonitorTool.ts","../../src/tools/ManageConnectionRequestsTool.ts","../../src/tools/AcceptConnectionRequestTool.ts","../../src/tools/RetrieveProfileTool.ts","../../src/tools/ListUnapprovedConnectionRequestsTool.ts","../../src/utils/state-tools.ts","../../src/state/open-convai-state.ts","../../src/plugins/BasePlugin.ts","../../src/plugins/hedera/HbarPricePlugin.ts","../../src/plugins/GenericPlugin.ts","../../src/plugins/HCS10Plugin.ts","../../src/plugins/openconvai/OpenConvAIPlugin.ts","../../src/plugins/PluginLoader.ts","../../src/plugins/PluginRegistry.ts","../../src/init/init.ts"],"sourcesContent":["import { TransactionReceipt, PrivateKey } from '@hashgraph/sdk';\nimport {\n HCS10Client as StandardSDKClient,\n AgentBuilder,\n InboundTopicType as StandardInboundTopicType,\n AIAgentCapability as StandardAIAgentCapability,\n AgentRegistrationResult,\n WaitForConnectionConfirmationResponse,\n ProfileResponse as SDKProfileResponse,\n HCSMessage,\n LogLevel,\n Logger,\n FeeConfigBuilderInterface,\n SocialPlatform,\n} from '@hashgraphonline/standards-sdk';\nimport { AgentMetadata, AgentChannels } from './types';\nimport { encryptMessage } from '../utils/Encryption';\nimport { IStateManager } from '../state/state-types';\n\n// Keep type alias as they were removed accidentally\ntype StandardHandleConnectionRequest = InstanceType<\n typeof StandardSDKClient\n>['handleConnectionRequest'];\ntype HandleConnectionRequestResponse = Awaited<\n ReturnType<StandardHandleConnectionRequest>\n>;\nexport type StandardNetworkType = 'mainnet' | 'testnet';\n\nexport interface ClientValidationOptions {\n accountId: string;\n privateKey: string;\n network?: StandardNetworkType;\n stateManager?: IStateManager;\n}\n\nexport interface HCSMessageWithTimestamp extends HCSMessage {\n timestamp: number;\n data?: string;\n sequence_number: number;\n}\n\nexport interface ExtendedAgentMetadata extends AgentMetadata {\n pfpBuffer?: Buffer;\n pfpFileName?: string;\n feeConfig?: FeeConfigBuilderInterface;\n}\n\n/**\n * HCS10Client wraps the HCS-10 functionalities using the @hashgraphonline/standards-sdk.\n * - Creates and registers agents using the standard SDK flow.\n * - Manages agent communication channels (handled by standard SDK).\n * - Sends messages on Hedera topics (currently manual, potential for standard SDK integration).\n */\nexport class HCS10Client {\n public standardClient: StandardSDKClient;\n private useEncryption: boolean;\n public agentChannels?: AgentChannels;\n public guardedRegistryBaseUrl: string;\n public logger: Logger;\n\n constructor(\n operatorId: string,\n operatorPrivateKey: string,\n network: StandardNetworkType,\n options?: {\n useEncryption?: boolean;\n registryUrl?: string;\n logLevel?: LogLevel;\n }\n ) {\n this.standardClient = new StandardSDKClient({\n network: network,\n operatorId: operatorId,\n operatorPrivateKey: operatorPrivateKey,\n guardedRegistryBaseUrl: options?.registryUrl,\n logLevel: options?.logLevel,\n });\n this.guardedRegistryBaseUrl = options?.registryUrl || '';\n this.useEncryption = options?.useEncryption || false;\n const shouldSilence = process.env.DISABLE_LOGGING === 'true';\n this.logger = new Logger({\n level: options?.logLevel || 'info',\n silent: shouldSilence,\n });\n }\n\n public getOperatorId(): string {\n const operator = this.standardClient.getClient().operatorAccountId;\n if (!operator) {\n throw new Error('Operator Account ID not configured in standard client.');\n }\n return operator.toString();\n }\n\n public getNetwork(): StandardNetworkType {\n return this.standardClient.getNetwork() as StandardNetworkType;\n }\n\n public async handleConnectionRequest(\n inboundTopicId: string,\n requestingAccountId: string,\n connectionRequestId: number,\n feeConfig?: FeeConfigBuilderInterface\n ): Promise<HandleConnectionRequestResponse> {\n try {\n const result = await this.standardClient.handleConnectionRequest(\n inboundTopicId,\n requestingAccountId,\n connectionRequestId,\n feeConfig\n );\n return result;\n } catch (error) {\n this.logger.error(\n `Error handling connection request #${connectionRequestId} for topic ${inboundTopicId}:`,\n error\n );\n throw new Error(\n `Failed to handle connection request: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n /**\n * Retrieves the profile for a given account ID using the standard SDK.\n */\n public async getAgentProfile(accountId: string): Promise<SDKProfileResponse> {\n return this.standardClient.retrieveProfile(accountId);\n }\n\n /**\n * Exposes the standard SDK's submitConnectionRequest method.\n */\n public async submitConnectionRequest(\n inboundTopicId: string,\n memo: string\n ): Promise<TransactionReceipt> {\n return this.standardClient.submitConnectionRequest(\n inboundTopicId,\n memo\n ) as Promise<TransactionReceipt>;\n }\n\n /**\n * Exposes the standard SDK's waitForConnectionConfirmation method.\n */\n public async waitForConnectionConfirmation(\n outboundTopicId: string,\n connectionRequestId: number,\n maxAttempts = 60,\n delayMs = 2000\n ): Promise<WaitForConnectionConfirmationResponse> {\n return this.standardClient.waitForConnectionConfirmation(\n outboundTopicId,\n connectionRequestId,\n maxAttempts,\n delayMs\n );\n }\n\n /**\n * Creates and registers an agent using the standard SDK's HCS10Client.\n * This handles account creation, key generation, topic setup, and registration.\n *\n * When metadata includes fee configuration:\n * 1. The properties.feeConfig will be passed to the AgentBuilder\n * 2. The properties.inboundTopicType will be set to FEE_BASED\n * 3. The SDK's createAndRegisterAgent will apply the fees to the agent's inbound topic\n *\n * @param metadata - The agent's metadata, potentially including pfpBuffer, pfpFileName,\n * and fee configuration in properties.feeConfig\n * @returns The registration result from the standard SDK, containing accountId, keys, topics etc.\n */\n public async createAndRegisterAgent(\n metadata: ExtendedAgentMetadata\n ): Promise<AgentRegistrationResult> {\n const builder = new AgentBuilder()\n .setName(metadata.name)\n .setBio(metadata.description || '')\n .setCapabilities(\n metadata.capabilities\n ? metadata.capabilities\n : [StandardAIAgentCapability.TEXT_GENERATION]\n )\n .setType((metadata.type || 'autonomous') as 'autonomous' | 'manual')\n .setModel(metadata.model || 'agent-model-2024')\n .setNetwork(this.getNetwork())\n .setInboundTopicType(StandardInboundTopicType.PUBLIC);\n\n if (metadata?.feeConfig) {\n builder.setInboundTopicType(StandardInboundTopicType.FEE_BASED);\n builder.setFeeConfig(metadata.feeConfig);\n }\n\n if (metadata.pfpBuffer && metadata.pfpFileName) {\n if (metadata.pfpBuffer.byteLength === 0) {\n this.logger.warn(\n 'Provided PFP buffer is empty. Skipping profile picture.'\n );\n } else {\n this.logger.info(\n `Setting profile picture: ${metadata.pfpFileName} (${metadata.pfpBuffer.byteLength} bytes)`\n );\n builder.setProfilePicture(metadata.pfpBuffer, metadata.pfpFileName);\n }\n } else {\n this.logger.warn(\n 'Profile picture not provided in metadata. Agent creation might fail if required by the underlying SDK builder.'\n );\n }\n\n if (metadata.social) {\n Object.entries(metadata.social).forEach(([platform, handle]) => {\n builder.addSocial(platform as SocialPlatform, handle);\n });\n }\n\n if (metadata.properties) {\n Object.entries(metadata.properties).forEach(([key, value]) => {\n builder.addProperty(key, value);\n });\n }\n\n try {\n const hasFees = Boolean(metadata?.feeConfig);\n const result = await this.standardClient.createAndRegisterAgent(builder, {\n initialBalance: hasFees ? 50 : undefined,\n });\n if (\n result?.metadata?.inboundTopicId &&\n result?.metadata?.outboundTopicId\n ) {\n this.agentChannels = {\n inboundTopicId: result.metadata.inboundTopicId,\n outboundTopicId: result.metadata.outboundTopicId,\n };\n }\n return result;\n } catch (error) {\n this.logger.error('Error during agent creation/registration:', error);\n throw new Error(\n `Failed to create/register agent: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n /**\n * Sends a structured HCS-10 message to the specified topic using the standard SDK client.\n * Handles potential inscription for large messages.\n *\n * @param topicId - The target topic ID (likely a connection topic).\n * @param operatorId - The operator ID string (e.g., \"inboundTopic@accountId\").\n * @param data - The actual message content/data.\n * @param memo - Optional memo for the message.\n * @param submitKey - Optional private key for topics requiring specific submit keys.\n * @returns A confirmation status string from the transaction receipt.\n */\n public async sendMessage(\n topicId: string,\n data: string,\n memo?: string,\n submitKey?: PrivateKey\n ): Promise<number | undefined> {\n if (this.useEncryption) {\n data = encryptMessage(data);\n }\n\n try {\n const messageResponse = await this.standardClient.sendMessage(\n topicId,\n data,\n memo,\n submitKey\n );\n return messageResponse.topicSequenceNumber?.toNumber();\n } catch (error) {\n this.logger.error(`Error sending message to topic ${topicId}:`, error);\n throw new Error(\n `Failed to send message: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n /**\n * Retrieves messages from a topic using the standard SDK client.\n *\n * @param topicId - The topic ID to get messages from.\n * @returns Messages from the topic, mapped to the expected format.\n */\n public async getMessages(topicId: string): Promise<{\n messages: HCSMessageWithTimestamp[];\n }> {\n try {\n const result = await this.standardClient.getMessages(topicId);\n\n const mappedMessages = result.messages.map((sdkMessage) => {\n const timestamp = sdkMessage?.created?.getTime() || 0;\n\n return {\n ...sdkMessage,\n timestamp: timestamp,\n data: sdkMessage.data,\n sequence_number: sdkMessage.sequence_number,\n };\n });\n mappedMessages.sort(\n (a: { timestamp: number }, b: { timestamp: number }) =>\n a.timestamp - b.timestamp\n );\n return { messages: mappedMessages };\n } catch (error) {\n this.logger.error(`Error getting messages from topic ${topicId}:`, error);\n return { messages: [] };\n }\n }\n\n public async getMessageStream(topicId: string): Promise<{\n messages: HCSMessage[];\n }> {\n return this.standardClient.getMessageStream(topicId);\n }\n\n /**\n * Retrieves content from an inscribed message using the standard SDK client.\n * @param inscriptionIdOrData - The inscription ID (hcs://...) or potentially raw data string.\n * @returns The resolved message content.\n */\n public async getMessageContent(inscriptionIdOrData: string): Promise<string> {\n try {\n const content = await this.standardClient.getMessageContent(\n inscriptionIdOrData\n );\n return content as string;\n } catch (error) {\n this.logger.error(\n `Error retrieving message content for: ${inscriptionIdOrData}`,\n error\n );\n throw new Error(\n `Failed to retrieve message content: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n /**\n * Retrieves the inbound topic ID associated with the current operator.\n * This typically involves fetching the operator's own HCS-10 profile.\n * @returns A promise that resolves to the operator's inbound topic ID.\n * @throws {Error} If the operator ID cannot be determined or the profile/topic cannot be retrieved.\n */\n public async getInboundTopicId(): Promise<string> {\n try {\n const operatorId = this.getOperatorId();\n this.logger.info(\n `[HCS10Client] Retrieving profile for operator ${operatorId} to find inbound topic...`\n );\n const profileResponse = await this.getAgentProfile(operatorId);\n if (profileResponse.success && profileResponse.topicInfo?.inboundTopic) {\n this.logger.info(\n `[HCS10Client] Found inbound topic for operator ${operatorId}: ${profileResponse.topicInfo.inboundTopic}`\n );\n return profileResponse.topicInfo.inboundTopic;\n } else {\n throw new Error(\n `Could not retrieve inbound topic from profile for ${operatorId}. Profile success: ${profileResponse.success}, Error: ${profileResponse.error}`\n );\n }\n } catch (error) {\n this.logger.error(\n `[HCS10Client] Error fetching operator's inbound topic ID (${this.getOperatorId()}):`,\n error\n );\n const operatorId = this.getOperatorId();\n let detailedMessage = `Failed to get inbound topic ID for operator ${operatorId}.`;\n if (\n error instanceof Error &&\n error.message.includes('does not have a valid HCS-11 memo')\n ) {\n detailedMessage += ` The account profile may not exist or is invalid. Please ensure this operator account (${operatorId}) is registered as an HCS-10 agent. You might need to register it first (e.g., using the 'register_agent' tool or SDK function).`;\n } else if (error instanceof Error) {\n detailedMessage += ` Reason: ${error.message}`;\n } else {\n detailedMessage += ` Unexpected error: ${String(error)}`;\n }\n throw new Error(detailedMessage);\n }\n }\n\n /**\n * Retrieves the configured operator account ID and private key.\n * Required by tools needing to identify the current agent instance.\n */\n public getAccountAndSigner(): { accountId: string; signer: PrivateKey } {\n const result = this.standardClient.getAccountAndSigner();\n return {\n accountId: result.accountId,\n signer: result.signer as unknown as PrivateKey,\n };\n }\n\n /**\n * Retrieves the outbound topic ID for the current operator.\n * Fetches the operator's profile if necessary.\n * @returns The outbound topic ID string.\n * @throws If the outbound topic cannot be determined.\n */\n public async getOutboundTopicId(): Promise<string> {\n const operatorId = this.getOperatorId();\n const profile = await this.getAgentProfile(operatorId);\n if (profile.success && profile.topicInfo?.outboundTopic) {\n return profile.topicInfo.outboundTopic;\n } else {\n throw new Error(\n `Could not retrieve outbound topic from profile for ${operatorId}. Profile success: ${profile.success}, Error: ${profile.error}`\n );\n }\n }\n\n public setClient(accountId: string, privateKey: string): StandardSDKClient {\n this.standardClient = new StandardSDKClient({\n network: this.getNetwork(),\n operatorId: accountId,\n operatorPrivateKey: privateKey,\n guardedRegistryBaseUrl: this.guardedRegistryBaseUrl,\n });\n return this.standardClient;\n }\n\n /**\n * Validates that the operator account exists and has proper access for agent operations\n */\n private async validateOperator(options: ClientValidationOptions): Promise<{\n isValid: boolean;\n operator?: { accountId: string };\n error?: string;\n }> {\n try {\n // Set up client with provided operator details\n this.setClient(options.accountId, options.privateKey);\n\n // Check if we can retrieve the operator ID\n const operatorId = this.getOperatorId();\n\n // If we got this far, basic validation passed\n return {\n isValid: true,\n operator: { accountId: operatorId },\n };\n } catch (error) {\n this.logger.error(`Validation error: ${error}`);\n return {\n isValid: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n }\n\n async initializeWithValidation(options: ClientValidationOptions): Promise<{\n isValid: boolean;\n operator?: { accountId: string };\n error?: string;\n }> {\n const validationResult = await this.validateOperator(options);\n\n if (validationResult.isValid) {\n // If we have access to the state manager, initialize its connections manager\n if (options.stateManager) {\n options.stateManager.initializeConnectionsManager(this.standardClient);\n }\n }\n\n return validationResult;\n }\n}\n","import {\n AIAgentCapability,\n Logger,\n FeeConfigBuilder,\n} from '@hashgraphonline/standards-sdk';\nimport { ensureAgentHasEnoughHbar } from '../utils/ensure-agent-has-hbar';\nimport { HCS10Client, ExtendedAgentMetadata } from '../hcs10/HCS10Client';\nimport { StructuredTool } from '@langchain/core/tools';\nimport { z } from 'zod';\nimport { IStateManager } from '../state/state-types';\nimport { AgentPersistenceOptions } from '../state/state-types';\nimport fs from 'fs';\nimport path from 'path';\nimport axios from 'axios';\n\n/**\n * Interface for HCS10 registration result\n */\ninterface HCS10RegistrationResult {\n metadata?: {\n accountId?: string;\n inboundTopicId?: string;\n outboundTopicId?: string;\n profileTopicId?: string;\n privateKey?: string;\n capabilities?: number[];\n [key: string]: string | number | boolean | number[] | object | undefined;\n };\n}\n\n/**\n * Agent registration details returned when successful\n */\ninterface AgentRegistrationDetails {\n success: boolean;\n message: string;\n name: string;\n accountId: string;\n privateKey: string;\n inboundTopicId: string;\n outboundTopicId: string;\n profileTopicId: string;\n capabilities: number[];\n hasFees: boolean;\n hbarFee: number;\n tokenFee: { amount: number; tokenId: string } | null;\n profilePicture?: {\n source: string;\n topicId?: string;\n };\n}\n\n/**\n * Profile picture input types supported by the tool\n */\ntype ProfilePictureInput =\n | string\n | {\n url: string;\n filename: string;\n }\n | {\n path: string;\n filename?: string;\n };\n\n/**\n * RegisterAgentTool wraps the createAndRegisterAgent() function of HCS10Client.\n * It creates and registers an agent on Hedera using the HCS-10 standard SDK flow.\n * On success, returns a JSON string containing the new agent's details (including private key).\n */\nexport class RegisterAgentTool extends StructuredTool {\n name = 'register_agent';\n description =\n \"Creates and registers the AI agent on the Hedera network. Returns JSON string with agent details (accountId, privateKey, topics) on success. Optionally supports fee configuration for the agent's inbound topic using HBAR or specific tokens.\";\n private client: HCS10Client;\n private stateManager?: IStateManager;\n\n schema = z.object({\n name: z.string().describe('The name of the agent to register'),\n description: z\n .string()\n .optional()\n .describe('Optional description of the agent'),\n type: z\n .enum(['autonomous', 'manual'])\n .optional()\n .describe('Optional agent type (default: autonomous)'),\n model: z\n .string()\n .optional()\n .describe('Optional model identifier for the agent'),\n capabilities: z\n .array(z.number())\n .optional()\n .describe(\n 'Optional array of AIAgentCapability enum values (0-18). If not provided, defaults to just TEXT_GENERATION (0)'\n ),\n profilePicture: z\n .union([\n z.string().describe('Path to a local image file or URL to an image'),\n z.object({\n url: z.string().describe('URL to an image file'),\n filename: z.string().describe('Filename to use for the image'),\n }),\n z.object({\n path: z.string().describe('Path to a local image file'),\n filename: z.string().optional().describe('Optional custom filename'),\n }),\n ])\n .optional()\n .describe(\n 'Optional profile picture for the agent (local file path or URL)'\n ),\n feeCollectorAccountId: z\n .string()\n .optional()\n .describe(\n \"The account ID to collect fees. If not specified, the new agent's account ID will be used. Required if any fee is specified.\"\n ),\n hbarFee: z\n .number()\n .optional()\n .describe(\n 'Optional: The fee amount in HBAR to charge per message on the inbound topic (e.g., 0.5). If specified, inboundTopicType will be set to FEE_BASED.'\n ),\n tokenFee: z\n .object({\n amount: z.number(),\n tokenId: z.string(),\n })\n .optional()\n .describe(\n 'Optional: The fee amount and token ID to charge per message on the inbound topic (e.g., { amount: 10, tokenId: \"0.0.12345\" }). If specified, inboundTopicType will be set to FEE_BASED.'\n ),\n hbarFees: z\n .array(\n z.object({\n amount: z.number(),\n collectorAccount: z.string().optional(),\n })\n )\n .optional()\n .describe(\n 'Optional: Array of HBAR fees with different collectors. If specified, inboundTopicType will be set to FEE_BASED.'\n ),\n tokenFees: z\n .array(\n z.object({\n amount: z.number(),\n tokenId: z.string(),\n collectorAccount: z.string().optional(),\n })\n )\n .optional()\n .describe(\n 'Optional: Array of token fees with different collectors. If specified, inboundTopicType will be set to FEE_BASED.'\n ),\n exemptAccountIds: z\n .array(z.string())\n .optional()\n .describe(\n 'Optional: Array of account IDs to exempt from ALL fees set for this agent.'\n ),\n setAsCurrent: z\n .boolean()\n .optional()\n .describe(\n 'Optional: Whether to set the newly registered agent as the current active agent in the state manager. Default: true'\n ),\n persistence: z\n .object({\n prefix: z.string().optional(),\n })\n .optional()\n .describe(\n 'Optional: Configuration for persisting agent data to environment variables. The prefix will determine the environment variable names (e.g., PREFIX_ACCOUNT_ID). Defaults to TODD if not specified.'\n ),\n });\n\n /**\n * Creates a new RegisterAgentTool instance\n * @param client - Instance of HCS10Client (already configured with operator/network)\n * @param stateManager - Optional state manager to store agent details\n */\n constructor(client: HCS10Client, stateManager?: IStateManager) {\n super();\n this.client = client;\n this.stateManager = stateManager;\n }\n\n /**\n * Loads a profile picture from a local file or URL and returns a buffer\n * @param profilePicture - Local file path or URL\n * @returns Object containing buffer and filename\n */\n private async loadProfilePicture(\n profilePicture: ProfilePictureInput\n ): Promise<{ buffer: Buffer; filename: string } | null> {\n const logger = Logger.getInstance({\n level: 'debug',\n });\n\n try {\n if (!profilePicture) {\n return null;\n }\n\n if (typeof profilePicture === 'string') {\n const isUrl =\n profilePicture.startsWith('http://') ||\n profilePicture.startsWith('https://');\n\n if (isUrl) {\n logger.info(`Loading profile picture from URL: ${profilePicture}`);\n const response = await axios.get(profilePicture, {\n responseType: 'arraybuffer',\n });\n const buffer = Buffer.from(response.data);\n\n const urlPathname = new URL(profilePicture).pathname;\n const filename = path.basename(urlPathname) || 'profile.png';\n\n return { buffer, filename };\n } else {\n if (!fs.existsSync(profilePicture)) {\n logger.warn(`Profile picture file not found: ${profilePicture}`);\n return null;\n }\n\n logger.info(`Loading profile picture from file: ${profilePicture}`);\n const buffer = fs.readFileSync(profilePicture);\n const filename = path.basename(profilePicture);\n\n return { buffer, filename };\n }\n }\n\n if ('url' in profilePicture) {\n logger.info(`Loading profile picture from URL: ${profilePicture.url}`);\n const response = await axios.get(profilePicture.url, {\n responseType: 'arraybuffer',\n });\n const buffer = Buffer.from(response.data);\n const filename = profilePicture.filename || 'profile.png';\n\n return { buffer, filename };\n }\n\n if ('path' in profilePicture) {\n if (!fs.existsSync(profilePicture.path)) {\n logger.warn(`Profile picture file not found: ${profilePicture.path}`);\n return null;\n }\n\n logger.info(\n `Loading profile picture from file: ${profilePicture.path}`\n );\n const buffer = fs.readFileSync(profilePicture.path);\n const filename =\n profilePicture.filename || path.basename(profilePicture.path);\n\n return { buffer, filename };\n }\n\n return null;\n } catch (error) {\n logger.error('Failed to load profile picture:', error);\n return null;\n }\n }\n\n /**\n * Calls createAndRegisterAgent() with the provided metadata.\n * Returns a JSON string with agent details on success, or an error string.\n */\n async _call(input: z.infer<typeof this.schema>): Promise<string> {\n const logger = Logger.getInstance({\n level: 'debug',\n });\n\n const metadata: ExtendedAgentMetadata = {\n name: input.name,\n description: input.description,\n type: input.type,\n model: input.model,\n capabilities: input.capabilities || [AIAgentCapability.TEXT_GENERATION],\n properties: {},\n };\n\n let profilePictureSource = '';\n if (input.profilePicture) {\n const profilePictureData = await this.loadProfilePicture(\n input.profilePicture\n );\n if (profilePictureData) {\n const { buffer, filename } = profilePictureData;\n metadata.pfpBuffer = buffer;\n metadata.pfpFileName = filename;\n\n if (typeof input.profilePicture === 'string') {\n profilePictureSource = input.profilePicture;\n } else if ('url' in input.profilePicture) {\n profilePictureSource = input.profilePicture.url;\n } else if ('path' in input.profilePicture) {\n profilePictureSource = input.profilePicture.path;\n }\n }\n }\n\n const hasHbarFee = input.hbarFee !== undefined && input.hbarFee > 0;\n const hasTokenFee = this.hasValidTokenFee(input.tokenFee);\n const hasHbarFees = input.hbarFees && input.hbarFees.length > 0;\n const hasTokenFees = input.tokenFees && input.tokenFees.length > 0;\n\n if (hasHbarFee || hasTokenFee || hasHbarFees || hasTokenFees) {\n const { accountId: operatorAccountId } =\n this.client.getAccountAndSigner();\n const collectorId = input.feeCollectorAccountId || operatorAccountId;\n\n if (!collectorId) {\n return 'Error: Fee collector account ID is required when specifying fees and could not be determined.';\n }\n\n const feeConfigBuilder = new FeeConfigBuilder({\n network: this.client.getNetwork(),\n logger,\n });\n\n try {\n const exemptAccountIds =\n input.exemptAccountIds?.filter(\n (id) => id !== collectorId && id.startsWith('0.0')\n ) || [];\n\n let updatedFeeConfig = feeConfigBuilder;\n\n if (hasHbarFee) {\n logger.info(\n `Adding HBAR fee: ${input.hbarFee} HBAR to be collected by ${collectorId}`\n );\n updatedFeeConfig = updatedFeeConfig.addHbarFee(\n input.hbarFee!,\n collectorId,\n exemptAccountIds\n );\n }\n\n if (hasHbarFees) {\n for (const fee of input.hbarFees!) {\n const feeCollector = fee.collectorAccount || collectorId;\n logger.info(\n `Adding HBAR fee: ${fee.amount} HBAR to be collected by ${feeCollector}`\n );\n updatedFeeConfig = updatedFeeConfig.addHbarFee(\n fee.amount,\n feeCollector,\n exemptAccountIds\n );\n }\n }\n\n if (hasTokenFee) {\n logger.info(\n `Adding token fee: ${input.tokenFee!.amount} of token ${\n input.tokenFee!.tokenId\n } to be collected by ${collectorId}`\n );\n updatedFeeConfig = await updatedFeeConfig.addTokenFee(\n input.tokenFee!.amount,\n input.tokenFee!.tokenId,\n collectorId,\n undefined,\n exemptAccountIds\n );\n }\n\n if (hasTokenFees) {\n for (const fee of input.tokenFees!) {\n const feeCollector = fee.collectorAccount || collectorId;\n logger.info(\n `Adding token fee: ${fee.amount} of token ${fee.tokenId} to be collected by ${feeCollector}`\n );\n updatedFeeConfig = await updatedFeeConfig.addTokenFee(\n fee.amount,\n fee.tokenId,\n feeCollector,\n undefined,\n exemptAccountIds\n );\n }\n }\n\n metadata.feeConfig = updatedFeeConfig;\n logger.info('FeeConfigBuilder created successfully');\n } catch (error) {\n return `Error: Failed to configure fees. Reason: ${\n error instanceof Error ? error.message : String(error)\n }`;\n }\n }\n\n try {\n logger.info('Registering agent with metadata');\n\n const result = (await this.client.createAndRegisterAgent(\n metadata\n )) as unknown as HCS10RegistrationResult;\n\n return this.processRegistrationResult(\n result,\n input,\n profilePictureSource\n );\n } catch (error) {\n return `Error: Failed to create/register agent \"${input.name}\". Reason: ${\n error instanceof Error ? error.message : String(error)\n }`;\n }\n }\n\n /**\n * Checks if the token fee configuration is valid\n */\n private hasValidTokenFee(tokenFee?: {\n amount: number;\n tokenId: string;\n }): boolean {\n return !!(\n tokenFee &&\n tokenFee.amount > 0 &&\n tokenFee.tokenId &&\n tokenFee.tokenId.trim() !== ''\n );\n }\n\n /**\n * Processes the registration result and returns formatted output\n */\n private async processRegistrationResult(\n result: HCS10RegistrationResult,\n input: z.infer<typeof this.schema>,\n profilePictureSource: string = ''\n ): Promise<string> {\n const newAgentAccountId = result?.metadata?.accountId || '';\n const inboundTopicId = result?.metadata?.inboundTopicId || '';\n const outboundTopicId = result?.metadata?.outboundTopicId || '';\n const profileTopicId = result?.metadata?.profileTopicId || '';\n const privateKey = result?.metadata?.privateKey || '';\n const pfpTopicId = result?.metadata?.pfpTopicId;\n\n this.validateRegistrationResult(\n newAgentAccountId,\n inboundTopicId,\n outboundTopicId,\n privateKey\n );\n\n if (\n this.stateManager &&\n privateKey &&\n newAgentAccountId &&\n inboundTopicId &&\n outboundTopicId &&\n (input.setAsCurrent === undefined || input.setAsCurrent)\n ) {\n const agent = {\n name: input.name,\n accountId: newAgentAccountId,\n inboundTopicId,\n outboundTopicId,\n profileTopicId,\n privateKey,\n pfpTopicId: pfpTopicId as string,\n };\n\n this.stateManager.setCurrentAgent(agent);\n\n if (this.stateManager.persistAgentData && input.persistence) {\n try {\n const persistenceOptions: AgentPersistenceOptions = {\n type: 'env-file',\n prefix: input.persistence.prefix,\n };\n\n await this.stateManager.persistAgentData(agent, persistenceOptions);\n } catch (error) {\n Logger.getInstance().warn('Failed to persist agent data', error);\n }\n }\n }\n\n await this.ensureAgentHasFunds(newAgentAccountId, input.name);\n\n const feeDescription = this.createFeeDescription(input);\n const feeMessage = feeDescription\n ? ` with ${feeDescription} fee on inbound topic`\n : '';\n\n const registrationDetails: AgentRegistrationDetails = {\n success: true,\n message: `Successfully registered agent '${input.name}'${feeMessage}.`,\n name: input.name,\n accountId: newAgentAccountId,\n privateKey: privateKey,\n inboundTopicId: inboundTopicId,\n outboundTopicId: outboundTopicId,\n profileTopicId: profileTopicId || 'N/A',\n capabilities: input.capabilities || [AIAgentCapability.TEXT_GENERATION],\n hasFees: !!(input.hbarFee || this.hasValidTokenFee(input.tokenFee)),\n hbarFee: input.hbarFee || 0,\n tokenFee: input.tokenFee || null,\n };\n\n if (pfpTopicId || profilePictureSource) {\n registrationDetails.profilePicture = {\n source: profilePictureSource,\n topicId: pfpTopicId as string,\n };\n }\n\n return JSON.stringify(registrationDetails);\n }\n\n /**\n * Ensures the agent has enough HBAR for operations\n */\n private async ensureAgentHasFunds(\n accountId: string,\n agentName: string\n ): Promise<void> {\n try {\n await ensureAgentHasEnoughHbar(\n Logger.getInstance({\n module: 'RegisterAgentTool',\n }),\n this.client.standardClient,\n accountId,\n agentName\n );\n } catch (error) {\n Logger.getInstance().error('Failed to auto fund agent', error);\n }\n }\n\n /**\n * Validates that all required fields are present in the registration result\n */\n private validateRegistrationResult(\n accountId?: string,\n inboundTopicId?: string,\n outboundTopicId?: string,\n privateKey?: string\n ): void {\n if (!accountId || !inboundTopicId || !outboundTopicId || !privateKey) {\n const missingFields = [\n !accountId && 'accountId',\n !inboundTopicId && 'inboundTopicId',\n !outboundTopicId && 'outboundTopicId',\n !privateKey && 'privateKey',\n ]\n .filter(Boolean)\n .join(', ');\n throw new Error(\n `Registration failed. The HCS client returned incomplete details (Missing: ${missingFields}).`\n );\n }\n }\n\n /**\n * Creates a description of the fees configured for the agent\n */\n private createFeeDescription(input: z.infer<typeof this.schema>): string {\n const hasHbarFee = input.hbarFee && input.hbarFee > 0;\n const hasTokenFee = this.hasValidTokenFee(input.tokenFee);\n if (!hasHbarFee && !hasTokenFee) {\n return '';\n }\n\n let description = '';\n if (hasHbarFee) {\n description += `${input.hbarFee} HBAR`;\n }\n if (hasTokenFee && input.tokenFee) {\n const tokenFeeText = `${input.tokenFee.amount} of token ${input.tokenFee.tokenId}`;\n description += description ? ` and ${tokenFeeText}` : tokenFeeText;\n }\n return description;\n }\n}\n","import { Hbar } from \"@hashgraph/sdk\";\nimport { TransferTransaction } from \"@hashgraph/sdk\";\nimport { Logger, HCS10Client, HederaMirrorNode } from \"@hashgraphonline/standards-sdk\";\n\nexport const MIN_REQUIRED_USD = 2.0;\nexport const MIN_REQUIRED_HBAR_USD = 10.0;\n\nexport async function ensureAgentHasEnoughHbar(\n logger: Logger,\n baseClient: HCS10Client,\n accountId: string,\n agentName: string\n): Promise<void> {\n try {\n const account = await baseClient.requestAccount(accountId);\n const balance = account.balance.balance;\n const hbarBalance = balance / 100_000_000;\n\n logger.info(`${agentName} account ${accountId} has ${hbarBalance} HBAR`);\n\n try {\n const mirrorNode = new HederaMirrorNode('testnet', logger);\n const hbarPrice = await mirrorNode.getHBARPrice(new Date());\n\n if (hbarPrice) {\n const balanceInUsd = hbarBalance * hbarPrice;\n logger.info(`${agentName} balance in USD: $${balanceInUsd.toFixed(2)}`);\n\n if (balanceInUsd < MIN_REQUIRED_USD) {\n logger.warn(\n `${agentName} account ${accountId} has less than $${MIN_REQUIRED_USD} (${balanceInUsd.toFixed(\n 2\n )}). Attempting to fund.`\n );\n\n try {\n const funder = baseClient.getAccountAndSigner();\n const targetHbar = MIN_REQUIRED_HBAR_USD / hbarPrice;\n const amountToTransferHbar = Math.max(0, targetHbar - hbarBalance);\n\n if (amountToTransferHbar > 0) {\n const transferTx = new TransferTransaction()\n .addHbarTransfer(\n funder.accountId,\n Hbar.fromTinybars(\n Math.round(amountToTransferHbar * -100_000_000)\n )\n )\n .addHbarTransfer(\n accountId,\n Hbar.fromTinybars(\n Math.round(amountToTransferHbar * 100_000_000)\n )\n );\n\n logger.info(\n `Funding ${agentName} account ${accountId} with ${amountToTransferHbar.toFixed(\n 2\n )} HBAR from ${funder.accountId}`\n );\n\n const fundTxResponse = await transferTx.execute(\n baseClient.getClient() as any\n );\n await fundTxResponse.getReceipt(baseClient.getClient() as any);\n logger.info(\n `Successfully funded ${agentName} account ${accountId}.`\n );\n } else {\n logger.info(\n `${agentName} account ${accountId} does not require additional funding.`\n );\n }\n } catch (fundingError) {\n logger.error(\n `Failed to automatically fund ${agentName} account ${accountId}:`,\n fundingError\n );\n logger.warn(\n `Please fund the account ${accountId} manually with at least ${(\n MIN_REQUIRED_HBAR_USD / hbarPrice\n ).toFixed(2)} HBAR.`\n );\n }\n }\n } else {\n logger.warn(\n 'Failed to get HBAR price from Mirror Node. Please ensure the account has enough HBAR.'\n );\n }\n } catch (error) {\n logger.warn(\n 'Failed to check USD balance. Please ensure the account has enough HBAR.'\n );\n }\n } catch (error) {\n logger.error(`Failed to check ${agentName} account balance:`, error);\n }\n}","import { HCS10Client } from '../hcs10/HCS10Client';\nimport { StructuredTool } from '@langchain/core/tools';\nimport { z } from 'zod';\nimport { Logger } from '@hashgraphonline/standards-sdk';\n\n/**\n * SendMessageTool wraps the sendMessage() function of HCS10Client.\n * It sends a message to a specified Hedera topic and monitors for responses.\n */\nexport class SendMessageTool extends StructuredTool {\n name = 'send_message';\n description =\n 'Sends a message to a specified Hedera topic using HCS-10 and monitors for responses.';\n private client: HCS10Client;\n private lastProcessedTimestamp: number = 0;\n private logger: Logger;\n\n schema = z.object({\n topicId: z.string().describe('The Hedera topic ID to send the message to'),\n message: z.string().describe('The message content to send'),\n disableMonitoring: z\n .boolean()\n .optional()\n .describe('Whether to disable monitoring for responses'),\n });\n\n /**\n * @param client - Instance of HCS10Client.\n */\n constructor(client: HCS10Client) {\n super();\n this.client = client;\n this.logger = Logger.getInstance({ module: 'SendMessageTool' });\n }\n\n /**\n * Calls sendMessage() with the provided parameters.\n */\n async _call(input: {\n topicId: string;\n message: string;\n disableMonitoring: boolean;\n }): Promise<string> {\n try {\n const result = await this.client.sendMessage(\n input.topicId,\n input.message\n );\n if (!result) {\n throw new Error('Failed to send message');\n }\n this.logger.info(`Message sent with sequence number ${result}`);\n if (!input.disableMonitoring) {\n const response = await this.monitorResponses(input.topicId, result);\n return `Successfully sent message to topic ${input.topicId}${\n response ? `\\nResponse: ${response}` : ''\n }`;\n } else {\n return `Successfully sent message to topic ${input.topicId}`;\n }\n } catch (error) {\n throw new Error(\n `Failed to send message: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n private async monitorResponses(\n topicId: string,\n sequenceNumber: number\n ): Promise<string | null> {\n const maxAttempts = 10;\n let attempts = 0;\n\n while (attempts < maxAttempts) {\n try {\n const messages = await this.client.getMessageStream(topicId);\n\n for (const message of messages.messages) {\n if (\n message.created &&\n message.created.getTime() > this.lastProcessedTimestamp\n ) {\n this.lastProcessedTimestamp = message.created.getTime();\n\n const content = await this.client.getMessageContent(message.data || '');\n\n let parsedContent;\n try {\n parsedContent = JSON.parse(content);\n } catch (error) {\n this.logger.error(`Error parsing message content: ${error}`);\n continue;\n }\n if (message.sequence_number > sequenceNumber) {\n // Unwrap nested data field if present\n if (parsedContent && typeof parsedContent.data === 'string') {\n return parsedContent.data;\n }\n return JSON.stringify(parsedContent);\n }\n }\n }\n } catch (error) {\n this.logger.error(`Error monitoring responses: ${error}`);\n }\n\n attempts++;\n await new Promise((resolve) => setTimeout(resolve, 1000));\n }\n\n return null;\n }\n}\n","import { HCS10Client } from '../hcs10/HCS10Client';\nimport { StructuredTool, ToolParams } from '@langchain/core/tools';\nimport { z } from 'zod';\n// Import FeeConfigBuilder if needed for explicit fee handling\n// import { FeeConfigBuilder } from '@hashgraphonline/standards-sdk';\nimport { Logger } from '@hashgraphonline/standards-sdk';\nimport {\n IStateManager,\n ActiveConnection,\n} from '../state/state-types'; // Corrected import path/name\n\nexport interface ConnectionToolParams extends ToolParams {\n client: HCS10Client;\n stateManager: IStateManager;\n}\n\n/**\n * ConnectionTool monitors the *current* agent's inbound topic for connection requests\n * and automatically handles them using the HCS-10 standard SDK flow.\n * Use this ONLY to passively LISTEN for other agents trying to connect TO YOU.\n * This tool takes NO arguments and does NOT start outgoing connections.\n */\nexport class ConnectionTool extends StructuredTool {\n name = 'monitor_connections';\n description =\n \"Starts passively LISTENING on the current agent's own inbound topic for INCOMING HCS-10 connection requests. Handles received requests automatically. Takes NO arguments. DO NOT use this to start a new connection TO someone else.\";\n public client: HCS10Client;\n public logger: Logger;\n private stateManager: IStateManager; // Renamed property\n private isMonitoring: boolean = false; // Flag to prevent multiple monitors\n private monitoringTopic: string | null = null;\n\n // Schema now takes NO arguments\n schema = z.object({});\n\n /**\n * @param client - Instance of HCS10Client.\n * @param stateManager - Instance of StateManager for shared state management.\n */\n constructor({ client, stateManager, ...rest }: ConnectionToolParams) {\n super(rest);\n this.client = client;\n this.stateManager = stateManager; // Renamed assignment\n this.logger = Logger.getInstance({\n module: 'ConnectionTool',\n level: 'info',\n });\n }\n\n /**\n * Initiates the connection request monitoring process in the background.\n * Gets the inbound topic ID from the configured client.\n */\n async _call(/* _input: z.infer<typeof this.schema> */): Promise<string> {\n // Get inboundTopicId from the client\n let inboundTopicId: string;\n try {\n // Assuming getInboundTopicId() is implemented and available\n inboundTopicId = await this.client.getInboundTopicId();\n } catch (error) {\n const errorMsg = `Error getting inbound topic ID for monitoring: ${\n error instanceof Error ? error.message : String(error)\n }`;\n this.logger.error(errorMsg);\n return errorMsg;\n }\n\n if (!inboundTopicId) {\n return 'Error: Could not determine the inbound topic ID for the current agent.';\n }\n\n if (this.isMonitoring) {\n if (this.monitoringTopic === inboundTopicId) {\n return `Already monitoring topic ${inboundTopicId}.`;\n } else {\n return `Error: Already monitoring a different topic (${this.monitoringTopic}). Stop the current monitor first.`;\n // TODO: Add a mechanism to stop the monitor if needed.\n }\n }\n\n this.isMonitoring = true;\n this.monitoringTopic = inboundTopicId;\n this.logger.info(\n `Initiating connection request monitoring for topic ${inboundTopicId}...`\n );\n\n // Start the monitoring process asynchronously without awaiting it\n // This allows the tool call to return quickly.\n this.monitorIncomingRequests(inboundTopicId).catch((error) => {\n this.logger.error(\n `Monitoring loop for ${inboundTopicId} encountered an unrecoverable error:`,\n error\n );\n this.isMonitoring = false; // Reset flag on loop failure\n this.monitoringTopic = null;\n });\n\n return `Started monitoring inbound topic ${inboundTopicId} for connection requests in the background.`;\n }\n\n /**\n * The core monitoring loop.\n */\n private async monitorIncomingRequests(inboundTopicId: string): Promise<void> {\n this.logger.info(`Monitoring inbound topic ${inboundTopicId}...`);\n\n let lastProcessedMessageSequence = 0;\n const processedRequestIds = new Set<number>(); // Track processed requests within this monitoring session\n\n // Main monitoring loop\n while (this.isMonitoring && this.monitoringTopic === inboundTopicId) {\n try {\n const messagesResult = await this.client.getMessages(inboundTopicId);\n\n const allMessages = messagesResult.messages;\n\n const connectionRequests = allMessages.filter(\n (msg) =>\n msg.op === 'connection_request' &&\n typeof msg.sequence_number === 'number' // Keep filtering by sequence number if needed, or remove if checking existing confirmations is sufficient\n // msg.sequence_number > lastProcessedMessageSequence // Temporarily remove or adjust this if checking confirmations is the primary method\n );\n\n for (const message of connectionRequests) {\n // Update lastProcessedMessageSequence regardless of handling outcome to avoid re-checking handled/skipped messages in future loops\n lastProcessedMessageSequence = Math.max(\n lastProcessedMessageSequence,\n message.sequence_number || 0 // Use 0 if sequence_number is undefined (though filter should prevent this)\n );\n\n const connectionRequestId = message.sequence_number;\n if (!connectionRequestId) {\n continue; // Skip if sequence number is missing\n }\n\n // --- Check if already handled ---\n const alreadyHandled = allMessages.some(\n (m) => m.op === 'connection_created' && m.connection_id === connectionRequestId\n );\n\n if (alreadyHandled) {\n this.logger.debug(\n `Connection request #${connectionRequestId} already handled (found connection_created). Skipping.`\n );\n continue; // Skip to the next request\n }\n // --- End Check ---\n\n // Extract requesting account ID from the message's operator_id field (topic@account)\n const senderOperatorId = message.operator_id || '';\n const requestingAccountId = senderOperatorId.split('@')[1] || null;\n\n if (!requestingAccountId) {\n this.logger.warn(\n `Could not determine requesting account ID from operator_id '${senderOperatorId}' for request #${connectionRequestId}. Skipping.`\n );\n continue;\n }\n\n if (processedRequestIds.has(connectionRequestId)) {\n this.logger.info(\n `Connection request #${connectionRequestId} already processed in this session. Skipping.`\n );\n continue;\n }\n\n this.logger.info(\n `Processing connection request #${connectionRequestId} from account ${requestingAccountId}...`\n );\n\n try {\n // Handle the connection request using the HCS10Client wrapper\n const confirmation = await this.client.handleConnectionRequest(\n inboundTopicId,\n requestingAccountId,\n connectionRequestId\n );\n\n processedRequestIds.add(connectionRequestId);\n this.logger.info(\n `Connection confirmed for request #${connectionRequestId}. New connection topic: ${confirmation.connectionTopicId}`\n );\n\n // Use stateManager to add connection\n const newConnection: ActiveConnection = {\n targetAccountId: requestingAccountId,\n targetAgentName: `Agent ${requestingAccountId}`,\n targetInboundTopicId: 'N/A',\n connectionTopicId: confirmation.connectionTopicId,\n };\n this.stateManager.addActiveConnection(newConnection);\n this.logger.info(\n `Added new active connection to ${requestingAccountId} state.`\n );\n } catch (handleError) {\n this.logger.error(\n `Error handling connection request #${connectionRequestId} from ${requestingAccountId}:`,\n handleError\n );\n }\n }\n } catch (error) {\n this.logger.error(\n `Error fetching or processing messages for topic ${inboundTopicId}:`,\n error\n );\n // Implement backoff or error threshold if needed\n }\n\n // Wait before the next poll\n await new Promise((resolve) => setTimeout(resolve, 5000)); // Poll every 5 seconds (adjust as needed)\n }\n\n this.logger.info(`Monitoring loop stopped for topic ${inboundTopicId}.`);\n this.isMonitoring = false; // Ensure flag is reset when loop exits\n this.monitoringTopic = null;\n }\n\n // Optional: Method to explicitly stop monitoring\n public stopMonitoring(): void {\n if (this.isMonitoring) {\n this.logger.info(\n `Stopping monitoring for topic ${this.monitoringTopic}...`\n );\n this.isMonitoring = false;\n this.monitoringTopic = null;\n } else {\n this.logger.info('Monitor is not currently running.');\n }\n }\n}\n","// src/tools/send-message-to-connection-tool.ts\n\nimport { StructuredTool, ToolParams } from '@langchain/core/tools';\nimport { z } from 'zod';\nimport { HCS10Client } from '../hcs10/HCS10Client';\nimport { IStateManager } from '../state/state-types';\nimport { Logger } from '@hashgraphonline/standards-sdk'; // Assuming logger utility\n\nexport interface SendMessageToConnectionToolParams extends ToolParams {\n hcsClient: HCS10Client;\n stateManager: IStateManager;\n}\n\n/**\n * A tool to send a message to an agent over an established HCS-10 connection.\n */\nexport class SendMessageToConnectionTool extends StructuredTool {\n name = 'send_message_to_connection';\n description =\n \"Sends a text message to another agent using an existing active connection. Identify the target agent using their account ID (e.g., 0.0.12345) or the connection number shown in 'list_connections'. Return back the reply from the target agent if possible\";\n schema = z.object({\n targetIdentifier: z\n .string()\n .describe(\n \"The account ID (e.g., 0.0.12345) of the target agent OR the connection number (e.g., '1', '2') from the 'list_connections' tool.\"\n ),\n message: z.string().describe('The text message content to send.'),\n disableMonitoring: z.boolean().optional().default(false),\n });\n\n private hcsClient: HCS10Client;\n private stateManager: IStateManager;\n private logger: Logger;\n\n constructor({\n hcsClient,\n stateManager,\n ...rest\n }: SendMessageToConnectionToolParams) {\n super(rest);\n this.hcsClient = hcsClient;\n this.stateManager = stateManager;\n this.logger = Logger.getInstance({ module: 'SendMessageToConnectionTool' });\n }\n\n protected async _call({\n targetIdentifier,\n message,\n disableMonitoring,\n }: z.infer<this['schema']>): Promise<string> {\n const currentAgent = this.stateManager.getCurrentAgent();\n if (!currentAgent) {\n return 'Error: Cannot send message. No agent is currently active. Please register or select an agent first.';\n }\n\n const connection =\n this.stateManager.getConnectionByIdentifier(targetIdentifier);\n if (!connection) {\n return `Error: Could not find an active connection matching identifier \"${targetIdentifier}\". Use 'list_connections' to see active connections.`;\n }\n\n const connectionTopicId = connection.connectionTopicId;\n const targetAgentName = connection.targetAgentName;\n\n // Construct the sender's operator ID\n const operatorId = `${currentAgent.inboundTopicId}@${currentAgent.accountId}`;\n\n this.logger.info(\n `Sending message from ${operatorId} to ${targetAgentName} (${connection.targetAccountId}) via connection topic ${connectionTopicId}`\n );\n\n try {\n // Call sendMessage with correct arguments\n const sequenceNumber = await this.hcsClient.sendMessage(\n connectionTopicId,\n message, // Message content as 'data'\n `Agent message from ${currentAgent.name}` // Optional memo\n );\n\n if (!sequenceNumber) {\n throw new Error('Failed to send message');\n }\n\n if (!disableMonitoring) {\n return `Message sent to ${targetAgentName} (${connection.targetAccountId}) via connection ${connectionTopicId}. Sequence Number: ${sequenceNumber}`;\n }\n\n const replyBack = await this.monitorResponses(\n connectionTopicId,\n operatorId,\n sequenceNumber\n );\n\n if (replyBack) {\n this.logger.info(`Got reply from ${targetAgentName}`, replyBack);\n // Format the return string clearly as an observation/reply\n return `Received reply from ${targetAgentName}: ${replyBack}`;\n }\n\n // Return message based on the status string if no reply was received/awaited\n return `Message sent to ${targetAgentName} (${connection.targetAccountId}) via connection ${connectionTopicId}. Sequence Number: ${sequenceNumber}`;\n } catch (error) {\n this.logger.error(\n `Failed to send message via connection ${connectionTopicId}: ${error}`\n );\n return `Error sending message to ${targetAgentName}: ${\n error instanceof Error ? error.message : String(error)\n }`;\n }\n }\n\n private async monitorResponses(\n topicId: string,\n operatorId: string,\n sequenceNumber: number\n ): Promise<string | null> {\n const maxAttempts = 30;\n const attempts = 0;\n\n while (attempts < maxAttempts) {\n try {\n const messages = await this.hcsClient.getMessageStream(topicId);\n\n for (const message of messages.messages) {\n if (\n message.sequence_number < sequenceNumber ||\n message.operator_id === operatorId\n ) {\n continue;\n }\n const content = await this.hcsClient.getMessageContent(message.data || '');\n\n return content;\n }\n } catch (error) {\n this.logger.error(`Error monitoring responses: ${error}`);\n }\n await new Promise((resolve) => setTimeout(resolve, 4000));\n }\n return null;\n }\n}\n","import { StructuredTool, ToolParams } from '@langchain/core/tools';\nimport { z } from 'zod';\nimport { HCS10Client } from '../hcs10/HCS10Client';\nimport { IStateManager, ActiveConnection } from '../state/state-types';\nimport { Logger } from '@hashgraphonline/standards-sdk';\n\nexport interface InitiateConnectionToolParams extends ToolParams {\n hcsClient: HCS10Client;\n stateManager: IStateManager;\n}\n\n/**\n * A tool to actively START a NEW HCS-10 connection TO a target agent.\n * Requires the target agent's account ID.\n * It retrieves their profile, sends a connection request, waits for confirmation, and stores the connection using the provided stateManager.\n * Use this tool ONLY to actively INITIATE an OUTGOING connection.\n */\nexport class InitiateConnectionTool extends StructuredTool {\n name = 'initiate_connection';\n description =\n 'Actively STARTS a NEW HCS-10 connection TO a specific target agent identified by their account ID. Requires the targetAccountId parameter. Use this ONLY to INITIATE an OUTGOING connection request.';\n schema = z.object({\n targetAccountId: z\n .string()\n .describe(\n 'The Hedera account ID (e.g., 0.0.12345) of the agent you want to connect with.'\n )\n });\n\n private hcsClient: HCS10Client;\n private stateManager: IStateManager;\n private logger: Logger;\n\n constructor({\n hcsClient,\n stateManager,\n ...rest\n }: InitiateConnectionToolParams) {\n super(rest);\n this.hcsClient = hcsClient;\n this.stateManager = stateManager;\n this.logger = Logger.getInstance({ module: 'InitiateConnectionTool' });\n }\n\n protected async _call({\n targetAccountId\n }: z.infer<this['schema']>): Promise<string> {\n const currentAgent = this.stateManager.getCurrentAgent();\n if (!currentAgent) {\n return 'Error: Cannot initiate connection. No agent is currently active. Please register or select an agent first.';\n }\n\n this.logger.info(\n `Attempting connection from ${currentAgent.accountId} to ${targetAccountId}`\n );\n\n try {\n this.logger.debug(`Retrieving profile for ${targetAccountId}...`);\n const targetProfile = await this.hcsClient.getAgentProfile(\n targetAccountId\n );\n if (!targetProfile?.topicInfo?.inboundTopic) {\n return `Error: Could not retrieve profile or find inbound topic ID for target agent ${targetAccountId}. They might not be registered or have a public profile.`;\n }\n const targetInboundTopicId = targetProfile.topicInfo.inboundTopic;\n const targetAgentName =\n targetProfile.profile.name || `Agent ${targetAccountId}`;\n\n const requestResult = await this.hcsClient.submitConnectionRequest(\n targetInboundTopicId,\n currentAgent.name\n );\n const sequenceNumberLong = requestResult?.topicSequenceNumber;\n if (!sequenceNumberLong) {\n throw new Error('Connection request sequence number not found.');\n }\n \n let connectionRequestId: number;\n try {\n connectionRequestId = sequenceNumberLong.toNumber();\n if (isNaN(connectionRequestId)) {\n throw new Error('Converted sequence number is NaN.');\n }\n } catch (conversionError) {\n throw new Error(\n `Failed to convert connection request sequence number: ${conversionError}`\n );\n }\n\n const confirmationTimeoutMs = 60000;\n const delayMs = 2000;\n const maxAttempts = Math.ceil(confirmationTimeoutMs / delayMs);\n\n const confirmationResult =\n await this.hcsClient.waitForConnectionConfirmation(\n targetInboundTopicId,\n connectionRequestId,\n maxAttempts,\n delayMs\n );\n\n if (!confirmationResult?.connectionTopicId) {\n return `Error: Connection confirmation not received from ${targetAccountId} (for request ${connectionRequestId}) within ${\n confirmationTimeoutMs / 1000\n } seconds.`;\n }\n\n const connectionTopicId = confirmationResult.connectionTopicId;\n this.logger.info(`Connection confirmed! Topic ID: ${connectionTopicId}`);\n\n const newConnection: ActiveConnection = {\n targetAccountId: targetAccountId,\n targetAgentName: targetAgentName,\n targetInboundTopicId: targetInboundTopicId,\n connectionTopicId: connectionTopicId,\n };\n this.stateManager.addActiveConnection(newConnection);\n\n const connections = this.stateManager.listConnections();\n const addedEntry = connections.find(\n (c) => c.connectionTopicId === connectionTopicId\n );\n const localConnectionId = addedEntry\n ? connections.indexOf(addedEntry) + 1\n : null;\n\n const idString = localConnectionId ? `#${localConnectionId}` : '';\n\n return `Successfully established connection ${idString} with ${targetAgentName} (${targetAccountId}). Connection Topic: ${connectionTopicId}. You can now send messages using this connection.`;\n } catch (error) {\n this.logger.error(`Connection initiation failed: ${error}`);\n return `Error initiating connection with ${targetAccountId}: ${\n error instanceof Error ? error.message : String(error)\n }`;\n }\n }\n}\n","import { StructuredTool, ToolParams } from '@langchain/core/tools';\nimport { z } from 'zod';\nimport { IStateManager, ActiveConnection } from '../state/state-types';\nimport { HCS10Client } from '../hcs10/HCS10Client';\nimport { Connection, Logger } from '@hashgraphonline/standards-sdk';\n\nexport interface ListConnectionsToolParams extends ToolParams {\n stateManager: IStateManager;\n hcsClient?: HCS10Client;\n}\n\n/**\n * A tool to list currently active HCS-10 connections stored in the state manager.\n * Enhanced to show more details similar to moonscape's implementation.\n */\nexport class ListConnectionsTool extends StructuredTool {\n name = 'list_connections';\n description =\n 'Lists the currently active HCS-10 connections with detailed information. Shows connection status, agent details, and recent activity. Use this to get a comprehensive view of all active connections.';\n schema = z.object({\n includeDetails: z\n .boolean()\n .optional()\n .describe(\n 'Whether to include detailed information about each connection'\n ),\n showPending: z\n .boolean()\n .optional()\n .describe('Whether to include pending connection requests'),\n });\n\n private stateManager: IStateManager;\n private hcsClient?: HCS10Client;\n private logger: Logger;\n\n constructor({ stateManager, hcsClient, ...rest }: ListConnectionsToolParams) {\n super(rest);\n this.stateManager = stateManager;\n this.hcsClient = hcsClient;\n this.logger = new Logger({ module: 'ListConnectionsTool' });\n }\n\n protected async _call(args: z.infer<this['schema']>): Promise<string> {\n const includeDetails = args.includeDetails ?? true;\n const showPending = args.showPending ?? true;\n\n const connections = await this.getEnhancedConnections();\n\n if (connections.length === 0) {\n return 'There are currently no active connections.';\n }\n\n const activeConnections = connections.filter(\n (c) => c.status === 'established'\n );\n\n const pendingConnections = connections.filter((c) => c.isPending);\n\n const needsConfirmation = connections.filter((c) => c.needsConfirmation);\n\n let output = '';\n\n if (activeConnections.length > 0) {\n output += `🟢 Active Connections (${activeConnections.length}):\\n`;\n activeConnections.forEach((conn, index) => {\n output += this.formatConnection(conn, index, includeDetails);\n });\n output += '\\n';\n }\n\n if (showPending && needsConfirmation.length > 0) {\n output += `🟠 Connections Needing Confirmation (${needsConfirmation.length}):\\n`;\n needsConfirmation.forEach((conn, index) => {\n output += this.formatConnection(conn, index, includeDetails);\n });\n output += '\\n';\n }\n\n if (showPending && pendingConnections.length > 0) {\n output += `⚪ Pending Connection Requests (${pendingConnections.length}):\\n`;\n pendingConnections.forEach((conn, index) => {\n output += this.formatConnection(conn, index, includeDetails);\n });\n }\n\n return output.trim();\n }\n\n private formatConnection(\n conn: Connection,\n index: number,\n includeDetails: boolean\n ): string {\n let output = `${index + 1}. ${\n conn.profileInfo?.display_name || conn.targetAgentName || 'Unknown Agent'\n } (${conn.targetAccountId})\\n`;\n const displayTopicId = conn.isPending\n ? '(Pending Request)'\n : conn.connectionTopicId;\n output += ` Topic: ${displayTopicId}\\n`;\n const statusText = conn.status || 'unknown';\n output += ` Status: ${statusText}\\n`;\n\n if (includeDetails) {\n if (conn.profileInfo?.bio) {\n output += ` Bio: ${conn.profileInfo.bio.substring(0, 100)}${\n conn.profileInfo.bio.length > 100 ? '...' : ''\n }\\n`;\n }\n\n if (conn.created) {\n const createdLabel = conn.isPending\n ? 'Request sent'\n : 'Connection established';\n output += ` ${createdLabel}: ${conn.created.toLocaleString()}\\n`;\n }\n\n if (conn.lastActivity) {\n output += ` Last activity: ${conn.lastActivity.toLocaleString()}\\n`;\n }\n }\n\n return output;\n }\n\n private async getEnhancedConnections(): Promise<Connection[]> {\n if (!this.hcsClient) {\n return this.stateManager.listConnections() as Connection[];\n }\n\n try {\n const { accountId } = this.hcsClient.getAccountAndSigner();\n if (!accountId) {\n return this.stateManager.listConnections() as Connection[];\n }\n\n const connectionManager = this.stateManager.getConnectionsManager();\n if (!connectionManager) {\n this.logger.error('ConnectionsManager not initialized');\n return this.stateManager.listConnections() as Connection[];\n }\n\n const connections = await connectionManager.fetchConnectionData(\n accountId\n );\n\n for (const connection of connections) {\n this.stateManager.updateOrAddConnection(connection as ActiveConnection);\n }\n\n return connections;\n } catch (error) {\n console.error('Error fetching connection data:', error);\n return this.stateManager.listConnections() as Connection[];\n }\n }\n}\n","import { StructuredTool, ToolParams } from '@langchain/core/tools';\nimport { z } from 'zod';\nimport { HCS10Client, HCSMessageWithTimestamp } from '../hcs10/HCS10Client';\nimport { IStateManager } from '../state/state-types';\nimport { Logger } from '@hashgraphonline/standards-sdk'; // Assuming logger utility\n\nexport interface CheckMessagesToolParams extends ToolParams {\n hcsClient: HCS10Client;\n stateManager: IStateManager;\n}\n\n/**\n * A tool to check for new messages on an active HCS-10 connection topic,\n * or optionally fetch the latest messages regardless of timestamp.\n */\nexport class CheckMessagesTool extends StructuredTool {\n name = 'check_messages';\n description = `Checks for and retrieves messages from an active connection. \nIdentify the target agent using their account ID (e.g., 0.0.12345) or the connection number shown in 'list_connections'. \nBy default, it only retrieves messages newer than the last check. \nUse 'fetchLatest: true' to get the most recent messages regardless of when they arrived. \nUse 'lastMessagesCount' to specify how many latest messages to retrieve (default 1 when fetchLatest is true).`;\n schema = z.object({\n targetIdentifier: z\n .string()\n .describe(\n \"The account ID (e.g., 0.0.12345) of the target agent OR the connection number (e.g., '1', '2') from the 'list_connections' tool to check messages for.\"\n ),\n fetchLatest: z\n .boolean()\n .optional()\n .default(false)\n .describe(\n 'Set to true to fetch the latest messages even if they have been seen before, ignoring the last checked timestamp. Defaults to false (fetching only new messages).'\n ),\n lastMessagesCount: z\n .number()\n .int()\n .positive()\n .optional()\n .describe(\n 'When fetchLatest is true, specifies how many of the most recent messages to retrieve. Defaults to 1.'\n ),\n });\n\n public hcsClient: HCS10Client;\n private stateManager: IStateManager;\n private logger: Logger;\n\n constructor({ hcsClient, stateManager, ...rest }: CheckMessagesToolParams) {\n super(rest);\n this.hcsClient = hcsClient;\n this.stateManager = stateManager;\n this.logger = Logger.getInstance({ module: 'CheckMessagesTool' });\n }\n\n protected async _call({\n targetIdentifier,\n fetchLatest,\n lastMessagesCount,\n }: z.infer<this['schema']>): Promise<string> {\n const connection =\n this.stateManager.getConnectionByIdentifier(targetIdentifier);\n\n if (!connection) {\n return `Error: Could not find an active connection matching identifier \"${targetIdentifier}\". Use 'list_connections' to see active connections.`;\n }\n\n const connectionTopicId = connection.connectionTopicId;\n const targetAgentName = connection.targetAgentName;\n const lastProcessedTimestamp =\n this.stateManager.getLastTimestamp(connectionTopicId);\n\n this.logger.info(\n `Checking messages for connection with ${targetAgentName} (${connection.targetAccountId}) on topic ${connectionTopicId} (fetchLatest: ${fetchLatest}, lastCount: ${lastMessagesCount}, since: ${lastProcessedTimestamp})`\n );\n\n try {\n // 1. Get messages from the topic\n const result = await this.hcsClient.getMessages(connectionTopicId);\n const allMessages = result.messages;\n\n if (!allMessages || allMessages.length === 0) {\n return `No messages found on connection topic ${connectionTopicId}.`;\n }\n\n let messagesToProcess: HCSMessageWithTimestamp[] = [];\n let latestTimestampNanos = lastProcessedTimestamp;\n const isFetchingLatest = fetchLatest === true;\n\n if (isFetchingLatest) {\n this.logger.info('Fetching latest messages regardless of timestamp.');\n const count = lastMessagesCount ?? 1;\n messagesToProcess = allMessages.slice(-count);\n } else {\n this.logger.info(\n `Filtering for messages newer than ${lastProcessedTimestamp}`\n );\n messagesToProcess = allMessages.filter((msg) => {\n const msgTimestampNanos = msg.timestamp * 1_000_000;\n return msgTimestampNanos > lastProcessedTimestamp;\n });\n \n if (messagesToProcess.length > 0) {\n latestTimestampNanos = messagesToProcess.reduce(\n (maxTs, msg) => Math.max(maxTs, msg.timestamp * 1_000_000),\n lastProcessedTimestamp\n );\n }\n }\n\n if (messagesToProcess.length === 0) {\n return isFetchingLatest\n ? `Could not retrieve the latest message(s). No messages found on topic ${connectionTopicId}.`\n : `No new messages found for connection with ${targetAgentName} since last check.`;\n }\n\n this.logger.info(`Processing ${messagesToProcess.length} message(s).`);\n\n // 3. Process messages (resolve inscriptions, format)\n let outputString = isFetchingLatest\n ? `Latest message(s) from ${targetAgentName}:\n`\n : `New messages from ${targetAgentName}:\n`;\n\n for (const msg of messagesToProcess) {\n let content = msg.data;\n try {\n // Check for inscription HRL\n if (typeof content === 'string' && content.startsWith('hcs://')) {\n this.logger.debug(`Resolving inscribed message: ${content}`);\n content = await this.hcsClient.getMessageContent(content);\n this.logger.debug(`Resolved content length: ${content?.length}`);\n }\n\n // Attempt to parse the content as the HCS-10 structure\n let displayContent = content; // Default to raw content\n try {\n const parsed = JSON.parse(content || '{}');\n if (\n parsed.p === 'hcs-10' &&\n parsed.op === 'message' &&\n parsed.data\n ) {\n // Extract sender and actual data from standard message format\n const senderOpId = parsed.operator_id || 'unknown_sender';\n displayContent = `[${senderOpId}]: ${parsed.data}`;\n } else {\n // If not standard format, maybe just show raw stringified version\n displayContent = content; // Keep raw if parsing worked but not expected format\n }\n } catch (parseError) {\n // Content wasn't JSON, keep raw content\n displayContent = content;\n }\n\n const messageDate = new Date(msg.timestamp);\n outputString += `\\n[${messageDate.toLocaleString()}] (Seq: ${\n msg.sequence_number\n })\n${displayContent}\n`;\n } catch (error) {\n const errorMsg = `Error processing message (Seq: ${\n msg.sequence_number\n }): ${error instanceof Error ? error.message : String(error)}`;\n this.logger.error(errorMsg);\n outputString += `\\n[Error processing message Seq: ${msg.sequence_number}]\\n`;\n }\n }\n\n // 4. Update the timestamp in demo state ONLY if fetching NEW messages\n if (!isFetchingLatest && latestTimestampNanos > lastProcessedTimestamp) {\n this.logger.debug(\n `Updating timestamp for topic ${connectionTopicId} to ${latestTimestampNanos}`\n );\n this.stateManager.updateTimestamp(\n connectionTopicId,\n latestTimestampNanos\n );\n }\n\n return outputString.trim();\n } catch (error) {\n this.logger.error(\n `Failed to check messages for topic ${connectionTopicId}: ${error}`\n );\n return `Error checking messages for ${targetAgentName}: ${\n error instanceof Error ? error.message : String(error)\n }`;\n }\n }\n}\n","import { StructuredTool, ToolParams } from '@langchain/core/tools';\nimport { z } from 'zod';\nimport { HCS10Client } from '../hcs10/HCS10Client';\nimport {\n AIAgentCapability,\n Logger,\n RegistrationSearchOptions,\n} from '@hashgraphonline/standards-sdk';\n\nexport interface FindRegistrationsToolParams extends ToolParams {\n hcsClient: HCS10Client;\n}\n\n/**\n * A tool to search for registered HCS-10 agents using the configured registry.\n */\nexport class FindRegistrationsTool extends StructuredTool {\n name = 'find_registrations';\n description =\n 'Searches the configured agent registry for HCS-10 agents. You can filter by account ID or tags. Returns basic registration info.';\n schema = z.object({\n accountId: z\n .string()\n .optional()\n .describe(\n 'Optional: Filter registrations by a specific Hedera account ID (e.g., 0.0.12345).'\n ),\n tags: z\n .array(z.nativeEnum(AIAgentCapability))\n .optional()\n .describe(\n 'Optional: Filter registrations by a list of tags (API filter only).'\n ),\n });\n\n private hcsClient: HCS10Client;\n private logger: Logger;\n\n constructor({ hcsClient, ...rest }: FindRegistrationsToolParams) {\n super(rest);\n this.hcsClient = hcsClient;\n this.logger = Logger.getInstance({ module: 'FindRegistrationsTool' });\n }\n\n protected async _call({\n accountId,\n tags,\n }: z.infer<this['schema']>): Promise<string> {\n this.logger.info(\n 'Searching registrations with filters - Account ID',\n JSON.stringify({\n accountId,\n tags,\n })\n );\n\n const options: RegistrationSearchOptions = {};\n if (accountId) {\n options.accountId = accountId;\n }\n if (tags && tags.length > 0) {\n options.tags = tags;\n }\n options.network = this.hcsClient.getNetwork();\n\n try {\n if (!this.hcsClient.standardClient) {\n throw new Error(\n 'Standard SDK client instance is not available in HCS10Client wrapper.'\n );\n }\n const result = await this.hcsClient.standardClient.findRegistrations(\n options\n );\n\n if (!result.success || result.error) {\n return `Error finding registrations: ${\n result.error || 'Unknown error'\n }`;\n }\n\n if (!result.registrations || result.registrations.length === 0) {\n return 'No registrations found matching the criteria.';\n }\n\n // Format the results based on available data from RegistrationSearchResult\n let output = `Found ${result.registrations.length} registration(s):\\n`;\n result.registrations.forEach((reg, index: number) => {\n const metadata = reg.metadata;\n output += `${index + 1}. Name: ${metadata.alias || 'N/A'}\\n`;\n output += `Description: ${metadata.bio || 'N/A'}\\n`;\n output += ` Account ID: ${reg.accountId}\\n`;\n output += ` Status: ${reg.status}\\n`;\n output += ` Model: ${metadata.properties?.model || 'N/A'}\\n`;\n if (metadata.properties?.capabilities && metadata.properties.capabilities.length > 0) {\n output += ` Capabilities: ${metadata.properties.capabilities.join(', ')}\\n`;\n }\n if (metadata.properties) {\n output += ` Properties: ${JSON.stringify(metadata.properties)}\\n`;\n }\n output += ` Inbound Topic: ${reg.inboundTopicId}\\n`;\n output += ` Outbound Topic: ${reg.outboundTopicId}\\n`;\n output += ` Created At: ${reg.createdAt}\\n`;\n });\n\n return output.trim();\n } catch (error) {\n this.logger.error(`Failed to execute findRegistrations: ${error}`);\n return `Error searching registrations: ${\n error instanceof Error ? error.message : String(error)\n }`;\n }\n }\n}\n","import { StructuredTool, ToolParams } from '@langchain/core/tools';\nimport { z } from 'zod';\nimport { HCS10Client } from '../hcs10/HCS10Client';\nimport {\n IStateManager,\n ActiveConnection,\n AgentProfileInfo,\n} from '../state/state-types';\nimport {\n Logger,\n FeeConfigBuilder,\n HCSMessage,\n FeeConfigBuilderInterface,\n AIAgentProfile,\n} from '@hashgraphonline/standards-sdk';\nimport { ListConnectionsTool } from './ListConnectionsTool';\n\nexport interface FeeDefinition {\n amount: number;\n collectorAccount?: string;\n}\n\nexport interface TokenFeeDefinition extends FeeDefinition {\n tokenId: string;\n}\n\nexport interface ConnectionMonitorToolParams extends ToolParams {\n hcsClient: HCS10Client;\n stateManager: IStateManager;\n}\n\n/**\n * A tool for monitoring incoming connection requests and accepting them with optional fee settings.\n */\nexport class ConnectionMonitorTool extends StructuredTool {\n name = 'monitor_connections';\n description =\n 'Monitors for incoming connection requests and accepts them with optional fee settings. Use this to watch for connection requests and accept them, optionally setting HBAR or token fees on the connection.';\n schema = z.object({\n acceptAll: z\n .boolean()\n .optional()\n .describe(\n 'Whether to automatically accept all incoming connection requests. Default is false.'\n ),\n targetAccountId: z\n .string()\n .optional()\n .describe(\n 'If provided, only accept connection requests from this specific account ID.'\n ),\n hbarFees: z\n .array(\n z.object({\n amount: z.number(),\n collectorAccount: z.string().optional(),\n })\n )\n .optional()\n .describe(\n 'Array of HBAR fee amounts to charge per message (with optional collector accounts).'\n ),\n tokenFees: z\n .array(\n z.object({\n amount: z.number(),\n tokenId: z.string(),\n collectorAccount: z.string().optional(),\n })\n )\n .optional()\n .describe(\n 'Array of token fee amounts and IDs to charge per message (with optional collector accounts).'\n ),\n exemptAccountIds: z\n .array(z.string())\n .optional()\n .describe(\n 'Array of account IDs to exempt from ALL fees set in this request.'\n ),\n monitorDurationSeconds: z\n .number()\n .optional()\n .describe(\n 'How long to monitor for incoming requests in seconds. Default is 60.'\n ),\n defaultCollectorAccount: z\n .string()\n .optional()\n .describe(\n 'Default account to collect fees if not specified at the fee level. Defaults to the agent account.'\n ),\n });\n\n private hcsClient: HCS10Client;\n private stateManager: IStateManager;\n private logger: Logger;\n private isMonitoring: boolean = false;\n private listConnectionsTool: ListConnectionsTool;\n\n constructor({\n hcsClient,\n stateManager,\n ...rest\n }: ConnectionMonitorToolParams) {\n super(rest);\n this.hcsClient = hcsClient;\n this.stateManager = stateManager;\n this.logger = Logger.getInstance({\n module: 'ConnectionMonitorTool',\n level: 'error',\n });\n this.listConnectionsTool = new ListConnectionsTool({\n stateManager,\n hcsClient,\n ...rest,\n });\n }\n\n updateClient(newClient: HCS10Client): void {\n this.hcsClient = newClient;\n this.logger.info('Updated HCS10Client instance for ConnectionMonitorTool');\n this.listConnectionsTool = new ListConnectionsTool({\n stateManager: this.stateManager,\n hcsClient: newClient,\n });\n }\n\n protected async _call({\n acceptAll = false,\n targetAccountId,\n hbarFees = [],\n tokenFees = [],\n exemptAccountIds,\n monitorDurationSeconds = 60,\n defaultCollectorAccount,\n }: z.infer<this['schema']>): Promise<string> {\n const currentAgent = this.stateManager.getCurrentAgent();\n if (!currentAgent) {\n return 'Error: Cannot monitor for connections. No agent is currently active. Please register or select an agent first.';\n }\n\n if (this.isMonitoring) {\n return 'Already monitoring for connection requests. Please wait for the current monitoring session to complete.';\n }\n\n try {\n this.isMonitoring = true;\n const inboundTopicId = await this.hcsClient.getInboundTopicId();\n\n if (!inboundTopicId) {\n this.isMonitoring = false;\n return 'Error: Could not find inbound topic ID for the current agent.';\n }\n\n this.logger.info(\n `Starting to monitor inbound topic ${inboundTopicId} for connection requests...`\n );\n\n const feeConfig = this.createFeeConfig(\n hbarFees,\n tokenFees,\n exemptAccountIds,\n targetAccountId,\n defaultCollectorAccount\n );\n\n const endTime = Date.now() + monitorDurationSeconds * 1000;\n const pollIntervalMs = 3000;\n let lastSequenceNumber = 0;\n let connectionRequestsFound = 0;\n let acceptedConnections = 0;\n let skippedRequests = 0;\n\n while (Date.now() < endTime) {\n try {\n await this.listConnectionsTool.invoke({\n includeDetails: false,\n showPending: false,\n });\n const currentConnections = this.stateManager.listConnections();\n\n // Create a map of connections by accountId and requestId to better track multiple connections\n const connectionsByAccountAndRequest = new Map<string, Set<string>>();\n\n currentConnections\n .filter((conn) => conn.status === 'established' && !conn.isPending)\n .forEach((conn) => {\n if (!connectionsByAccountAndRequest.has(conn.targetAccountId)) {\n connectionsByAccountAndRequest.set(\n conn.targetAccountId,\n new Set()\n );\n }\n\n if (conn.connectionRequestId) {\n connectionsByAccountAndRequest\n .get(conn.targetAccountId)\n ?.add(String(conn.connectionRequestId));\n }\n });\n\n const messagesResult = await this.hcsClient.getMessages(\n inboundTopicId\n );\n const newMessages = messagesResult.messages.filter((msg) => {\n if (\n !msg.sequence_number ||\n msg.sequence_number <= lastSequenceNumber\n ) {\n return false;\n }\n lastSequenceNumber = Math.max(\n lastSequenceNumber,\n msg.sequence_number\n );\n return msg.op === 'connection_request';\n });\n\n for (const request of newMessages) {\n const requestId = request.sequence_number;\n if (!requestId) {\n continue;\n }\n\n connectionRequestsFound++;\n\n // Get the inbound topic ID where this request was received\n const inboundTopicId =\n (await this.hcsClient.getInboundTopicId()) || '';\n\n // Get ConnectionsManager from state manager\n const connectionsManager =\n this.stateManager.getConnectionsManager();\n if (!connectionsManager) {\n this.logger.error(\n 'ConnectionsManager not initialized in state manager'\n );\n continue;\n }\n\n // Check if we've already processed this specific request\n if (\n connectionsManager.isConnectionRequestProcessed(\n inboundTopicId,\n requestId\n )\n ) {\n this.logger.info(\n `Request #${requestId} already processed, skipping`\n );\n skippedRequests++;\n continue;\n }\n\n const requestorAccountId = this.extractAccountId(request);\n if (!requestorAccountId) {\n // Mark as processed even if we couldn't extract the account ID\n connectionsManager.markConnectionRequestProcessed(\n inboundTopicId,\n requestId\n );\n continue;\n }\n\n if (targetAccountId && requestorAccountId !== targetAccountId) {\n this.logger.info(\n `Request #${requestId} doesn't match target ${targetAccountId}`\n );\n continue;\n }\n\n // Check if this specific request has already been processed\n const existingAccountConnections =\n connectionsByAccountAndRequest.get(requestorAccountId);\n if (existingAccountConnections?.has(String(requestId))) {\n this.logger.info(\n `Already processed connection request #${requestId} from ${requestorAccountId}, skipping`\n );\n connectionsManager.markConnectionRequestProcessed(\n inboundTopicId,\n requestId\n );\n skippedRequests++;\n continue;\n }\n\n if (acceptAll) {\n const result = await this.acceptConnectionRequest(\n requestId,\n requestorAccountId,\n feeConfig\n );\n connectionsManager.markConnectionRequestProcessed(\n inboundTopicId,\n requestId\n );\n\n if (result.success) {\n acceptedConnections++;\n this.logger.info(\n `Successfully accepted connection with ${requestorAccountId} for request #${requestId}`\n );\n }\n } else {\n this.logger.info(\n `Found request #${requestId} from ${requestorAccountId} (not auto-accepting)`\n );\n }\n }\n\n await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));\n } catch (error) {\n this.logger.error(`Error polling for messages: ${error}`);\n await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));\n }\n }\n\n this.isMonitoring = false;\n\n if (connectionRequestsFound === 0) {\n return `No connection requests received during the ${monitorDurationSeconds} second monitoring period.`;\n } else if (acceptAll) {\n return `Monitored for ${monitorDurationSeconds} seconds. Found ${connectionRequestsFound} connection requests, accepted ${acceptedConnections} connections, skipped ${skippedRequests} existing connections${this.formatFeeString(\n hbarFees,\n tokenFees\n )}.`;\n } else {\n return `Monitored for ${monitorDurationSeconds} seconds. Found ${connectionRequestsFound} connection requests. To accept them, call this tool again with acceptAll=true.`;\n }\n } catch (error) {\n this.isMonitoring = false;\n this.logger.error(`Connection monitoring failed: ${error}`);\n return `Error monitoring for connections: ${\n error instanceof Error ? error.message : String(error)\n }`;\n }\n }\n\n private createFeeConfig(\n hbarFees: FeeDefinition[] = [],\n tokenFees: TokenFeeDefinition[] = [],\n exemptAccountIds?: string[],\n targetAccountId?: string,\n defaultCollectorAccount?: string\n ): FeeConfigBuilderInterface | undefined {\n if (hbarFees.length === 0 && tokenFees.length === 0) {\n return undefined;\n }\n\n try {\n const agentAccountId = this.hcsClient.getAccountAndSigner().accountId;\n const defaultCollector = defaultCollectorAccount || agentAccountId;\n\n const builder = new FeeConfigBuilder({\n network: this.hcsClient.getNetwork(),\n logger: this.logger,\n defaultCollectorAccountId: defaultCollector,\n });\n\n const exemptIds = [...(exemptAccountIds || [])];\n if (targetAccountId && !exemptIds.includes(targetAccountId)) {\n exemptIds.push(targetAccountId);\n }\n\n for (const hbarFee of hbarFees) {\n if (hbarFee.amount > 0) {\n const collector = hbarFee.collectorAccount || defaultCollector;\n builder.addHbarFee(hbarFee.amount, collector, exemptIds);\n this.logger.info(\n `Added HBAR fee: ${hbarFee.amount} HBAR to be collected by ${collector}`\n );\n }\n }\n\n for (const tokenFee of tokenFees) {\n if (tokenFee.amount > 0 && tokenFee.tokenId) {\n const collector = tokenFee.collectorAccount || defaultCollector;\n builder.addTokenFee(\n tokenFee.amount,\n tokenFee.tokenId,\n collector,\n undefined,\n exemptIds\n );\n this.logger.info(\n `Added token fee: ${tokenFee.amount} of token ${tokenFee.tokenId} to be collected by ${collector}`\n );\n }\n }\n\n return builder;\n } catch (error) {\n this.logger.error(`Error creating fee configuration: ${error}`);\n return undefined;\n }\n }\n\n private extractAccountId(request: HCSMessage): string | undefined {\n if (request.operator_id) {\n return this.hcsClient.standardClient.extractAccountFromOperatorId(\n request.operator_id\n );\n }\n return undefined;\n }\n\n private async acceptConnectionRequest(\n connectionRequestId: number,\n requestingAccountId: string,\n feeConfig?: FeeConfigBuilderInterface\n ): Promise<{ success: boolean; connectionTopicId?: string; error?: string }> {\n try {\n const inboundTopicId = await this.hcsClient.getInboundTopicId();\n this.logger.info(\n `Accepting connection request #${connectionRequestId} from ${requestingAccountId}`\n );\n\n const result = await this.hcsClient.handleConnectionRequest(\n inboundTopicId,\n requestingAccountId,\n connectionRequestId,\n feeConfig\n );\n\n if (!result?.connectionTopicId) {\n return {\n success: false,\n error: 'Connection acceptance returned no connection topic ID',\n };\n }\n\n const connectionTopicId = result.connectionTopicId;\n this.logger.info(\n `Connection established! Topic ID: ${connectionTopicId}`\n );\n\n let profileInfo: AIAgentProfile | undefined;\n try {\n const profile = await this.hcsClient.getAgentProfile(\n requestingAccountId\n );\n if (profile.success && profile.profile) {\n profileInfo = profile.profile;\n }\n } catch (profileError) {\n this.logger.warn(\n `Could not fetch profile for ${requestingAccountId}: ${profileError}`\n );\n }\n\n const targetInboundTopicId =\n (await this.hcsClient.getAgentProfile(requestingAccountId))?.topicInfo\n ?.inboundTopic || '';\n\n const connection: ActiveConnection = {\n targetAccountId: requestingAccountId,\n targetAgentName:\n profileInfo?.display_name || `Agent ${requestingAccountId}`,\n targetInboundTopicId,\n connectionTopicId,\n profileInfo,\n created: new Date(),\n status: 'established',\n metadata: {\n requestId: connectionRequestId,\n },\n };\n\n this.stateManager.addActiveConnection(connection);\n\n return {\n success: true,\n connectionTopicId,\n };\n } catch (error) {\n this.logger.error(`Error accepting connection request: ${error}`);\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n }\n\n private formatFeeString(\n hbarFees: FeeDefinition[] = [],\n tokenFees: TokenFeeDefinition[] = []\n ): string {\n if (hbarFees.length === 0 && tokenFees.length === 0) {\n return '';\n }\n\n let feeString = ' with fees: ';\n\n if (hbarFees.length > 0) {\n const hbarFeeDetails = hbarFees\n .filter((fee) => fee.amount > 0)\n .map((fee) => {\n const collector = fee.collectorAccount\n ? ` to ${fee.collectorAccount}`\n : '';\n return `${fee.amount} HBAR${collector}`;\n })\n .join(', ');\n\n if (hbarFeeDetails) {\n feeString += hbarFeeDetails;\n }\n }\n\n if (tokenFees.length > 0) {\n if (hbarFees.length > 0) {\n feeString += ' and ';\n }\n\n const tokenFeeDetails = tokenFees\n .filter((fee) => fee.amount > 0 && fee.tokenId)\n .map((fee) => {\n const collector = fee.collectorAccount\n ? ` to ${fee.collectorAccount}`\n : '';\n return `${fee.amount} of token ${fee.tokenId}${collector}`;\n })\n .join(', ');\n\n if (tokenFeeDetails) {\n feeString += tokenFeeDetails;\n }\n }\n\n return feeString === ' with fees: ' ? '' : feeString;\n }\n\n /**\n * Updates the ConnectionsManager with latest connection data\n * This method is meant to be called when changes to connections happen\n * outside this tool's monitoring process\n */\n public update(): void {\n // Trigger the listConnectionsTool to refresh state data\n this.listConnectionsTool\n .invoke({\n includeDetails: true,\n showPending: true,\n })\n .catch((error) => {\n this.logger.error(`Error updating connections: ${error}`);\n });\n }\n}\n","import { StructuredTool, ToolParams } from '@langchain/core/tools';\nimport { z } from 'zod';\nimport { HCS10Client } from '../hcs10/HCS10Client';\nimport { IStateManager } from '../state/state-types';\nimport { Logger } from '@hashgraphonline/standards-sdk';\n\nexport interface ManageConnectionRequestsToolParams extends ToolParams {\n hcsClient: HCS10Client;\n stateManager: IStateManager;\n}\n\n/**\n * A tool for managing incoming connection requests in a LangChain-compatible way.\n * This tool allows an agent to list, view details of, and accept/reject incoming connection requests.\n */\nexport class ManageConnectionRequestsTool extends StructuredTool {\n name = 'manage_connection_requests';\n description =\n 'Manage incoming connection requests. List pending requests, view details about requesting agents, and reject connection requests. Use the separate \"accept_connection_request\" tool to accept.';\n schema = z.object({\n action: z\n .enum(['list', 'view', 'reject'])\n .describe(\n 'The action to perform: list all requests, view details of a specific request, or reject a request'\n ),\n requestKey: z\n .string()\n .optional()\n .describe(\n 'The unique request key to view or reject (required for view and reject actions)'\n ),\n });\n\n private hcsClient: HCS10Client;\n private stateManager: IStateManager;\n private logger: Logger;\n private lastRefreshTime: number = 0;\n private refreshIntervalMs = 30000;\n\n constructor({\n hcsClient,\n stateManager,\n ...rest\n }: ManageConnectionRequestsToolParams) {\n super(rest);\n this.hcsClient = hcsClient;\n this.stateManager = stateManager;\n this.logger = Logger.getInstance({\n module: 'ManageConnectionRequestsTool',\n level: 'debug',\n });\n }\n\n protected async _call({\n action,\n requestKey,\n }: z.infer<this['schema']>): Promise<string> {\n const currentAgent = this.stateManager.getCurrentAgent();\n if (!currentAgent) {\n return 'Error: Cannot manage connection requests. No agent is currently active. Please register or select an agent first.';\n }\n\n if ((action === 'view' || action === 'reject') && requestKey === undefined) {\n return `Error: Request key is required for the \"${action}\" action. Use the \"list\" action first to see available requests.`;\n }\n\n try {\n await this.refreshRequestsIfNeeded();\n\n switch (action) {\n case 'list':\n return this.listRequests();\n case 'view':\n return this.viewRequest(requestKey!);\n case 'reject':\n return this.rejectRequest(requestKey!);\n default:\n return `Error: Unsupported action: ${action}`;\n }\n } catch (error) {\n this.logger.error(`Error in ManageConnectionRequestsTool: ${error}`);\n return `Error managing connection requests: ${\n error instanceof Error ? error.message : String(error)\n }`;\n }\n }\n\n private async refreshRequestsIfNeeded(): Promise<void> {\n const now = Date.now();\n if (now - this.lastRefreshTime > this.refreshIntervalMs) {\n await this.refreshRequests();\n this.lastRefreshTime = now;\n }\n }\n\n private async refreshRequests(): Promise<void> {\n try {\n const { accountId } = this.hcsClient.getAccountAndSigner();\n if (!accountId) {\n throw new Error('Could not determine account ID for current agent');\n }\n\n const connectionManager = this.stateManager.getConnectionsManager();\n if (!connectionManager) {\n throw new Error('ConnectionsManager not initialized');\n }\n\n await connectionManager.fetchConnectionData(accountId);\n } catch (error) {\n this.logger.error(`Error refreshing connection requests: ${error}`);\n throw error;\n }\n }\n\n private listRequests(): string {\n const connectionsManager = this.stateManager.getConnectionsManager();\n if (!connectionsManager) {\n return 'Error: ConnectionsManager not initialized';\n }\n\n const pendingRequests = connectionsManager.getPendingRequests();\n const needsConfirmation =\n connectionsManager.getConnectionsNeedingConfirmation();\n\n const allRequests = [...pendingRequests, ...needsConfirmation];\n\n if (allRequests.length === 0) {\n console.log('No pending connection requests found.', allRequests);\n return 'No pending connection requests found.';\n }\n\n let output = `Found ${allRequests.length} pending connection request(s):\\n\\n`;\n const sortedRequests = [...allRequests].sort(\n (a, b) => b.created.getTime() - a.created.getTime()\n );\n\n sortedRequests.forEach((request, index) => {\n // Create a display ID for the connection request\n const requestType = request.needsConfirmation ? '🟠 Incoming' : '⚪️ Outgoing';\n const requestIdDisplay = request.uniqueRequestKey ||\n `${request.connectionRequestId || request.inboundRequestId || 'unknown'}`;\n\n output += `${index + 1}. ${requestType} - Key: ${requestIdDisplay}\\n`;\n output += ` ${request.needsConfirmation ? 'From' : 'To'}: ${\n request.targetAgentName || `Agent ${request.targetAccountId}`\n } (${request.targetAccountId})\\n`;\n output += ` Sent/Rcvd: ${request.created.toLocaleString()}\\n`;\n\n if (request.memo) {\n output += ` Memo: ${request.memo}\\n`;\n }\n\n if (request.profileInfo && request.profileInfo.bio) {\n output += ` Bio: ${request.profileInfo.bio}\\n`;\n }\n\n output += '\\n';\n });\n\n output +=\n 'To view more details about a request, use action=\"view\" with the specific requestKey.\\n';\n output +=\n 'To reject a request, use action=\"reject\" with the specific requestKey.';\n return output;\n }\n\n private viewRequest(requestKey: string): string {\n const connectionsManager = this.stateManager.getConnectionsManager();\n if (!connectionsManager) {\n return 'Error: ConnectionsManager not initialized';\n }\n\n const pendingRequests = connectionsManager.getPendingRequests();\n const needsConfirmation =\n connectionsManager.getConnectionsNeedingConfirmation();\n\n const allRequests = [...pendingRequests, ...needsConfirmation];\n\n // Find the request with the matching unique key or fallback to sequence number\n const request = allRequests.find(\n (r) =>\n (r.uniqueRequestKey === requestKey) ||\n (r.connectionRequestId?.toString() === requestKey) ||\n (r.inboundRequestId?.toString() === requestKey)\n );\n\n if (!request) {\n return `Error: Request with key ${requestKey} not found or no longer pending.`;\n }\n\n // Create a display ID for the connection request\n const requestType = request.needsConfirmation ? 'Incoming' : 'Outgoing';\n const uniqueKey = request.uniqueRequestKey ||\n `${request.connectionRequestId || request.inboundRequestId || 'unknown'}`;\n\n let output = `Details for ${requestType} connection request: ${uniqueKey}\\n\\n`;\n output += `${request.needsConfirmation ? 'Requestor' : 'Target'} ID: ${request.targetAccountId}\\n`;\n output += `${request.needsConfirmation ? 'Requestor' : 'Target'} Name: ${\n request.targetAgentName || `Agent ${request.targetAccountId}`\n }\\n`;\n output += `Received: ${request.created.toLocaleString()}\\n`;\n\n if (request.memo) {\n output += `Memo: ${request.memo}\\n`;\n }\n\n if (request.profileInfo) {\n output += '\\nAgent Profile Information:\\n';\n\n if (request.profileInfo.display_name || request.profileInfo.alias) {\n output += `Name: ${\n request.profileInfo.display_name || request.profileInfo.alias\n }\\n`;\n }\n\n if (request.profileInfo.type !== undefined) {\n output += `Type: ${request.profileInfo.type}\\n`;\n }\n\n if (request.profileInfo.bio) {\n output += `Bio: ${request.profileInfo.bio}\\n`;\n }\n }\n\n output += '\\nActions:\\n';\n output += `- To reject this request: action=\"reject\", requestKey=\"${uniqueKey}\"\\n`;\n output +=\n 'Use the separate \"accept_connection_request\" tool to accept requests.';\n return output;\n }\n\n private async rejectRequest(requestKey: string): Promise<string> {\n const connectionsManager = this.stateManager.getConnectionsManager();\n if (!connectionsManager) {\n return 'Error: ConnectionsManager not initialized';\n }\n\n const pendingRequests = connectionsManager.getPendingRequests();\n const needsConfirmation =\n connectionsManager.getConnectionsNeedingConfirmation();\n\n const allRequests = [...pendingRequests, ...needsConfirmation];\n\n // Find the request with the matching unique key or fallback to sequence number\n const request = allRequests.find(\n (r) =>\n (r.uniqueRequestKey === requestKey) ||\n (r.connectionRequestId?.toString() === requestKey) ||\n (r.inboundRequestId?.toString() === requestKey)\n );\n\n if (!request) {\n return `Error: Request with key ${requestKey} not found or no longer pending.`;\n }\n\n // Mark as processed in ConnectionsManager based on the appropriate ID\n if (request.inboundRequestId) {\n // For needs_confirmation requests\n connectionsManager.markConnectionRequestProcessed(\n request.targetInboundTopicId || '',\n request.inboundRequestId\n );\n } else if (request.connectionRequestId) {\n // For pending requests\n connectionsManager.markConnectionRequestProcessed(\n request.originTopicId || '',\n request.connectionRequestId\n );\n }\n\n return `Connection request from ${\n request.targetAgentName || `Agent ${request.targetAccountId}`\n } was rejected.`;\n }\n}\n","import { StructuredTool, ToolParams } from '@langchain/core/tools';\nimport { z } from 'zod';\nimport { HCS10Client } from '../hcs10/HCS10Client';\nimport { IStateManager, ActiveConnection } from '../state/state-types';\nimport { Logger, FeeConfigBuilder } from '@hashgraphonline/standards-sdk';\n\nexport interface AcceptConnectionRequestToolParams extends ToolParams {\n hcsClient: HCS10Client;\n stateManager: IStateManager;\n}\n\n/**\n * A tool specifically for accepting incoming connection requests.\n */\nexport class AcceptConnectionRequestTool extends StructuredTool {\n name = 'accept_connection_request';\n description =\n 'Accepts a specific pending connection request from another agent, establishing a communication channel.';\n schema = z.object({\n requestKey: z\n .string()\n .describe(\n 'The unique request key of the specific request to accept. Use the \"manage_connection_requests\" tool with action=\"list\" first to get valid keys.'\n ),\n hbarFee: z\n .number()\n .optional()\n .describe(\n 'Optional HBAR fee amount to charge the connecting agent per message on the new connection topic.'\n ),\n exemptAccountIds: z\n .array(z.string())\n .optional()\n .describe(\n 'Optional list of account IDs to exempt from any configured fees on the new connection topic.'\n ),\n });\n\n private hcsClient: HCS10Client;\n private stateManager: IStateManager;\n private logger: Logger;\n\n constructor({\n hcsClient,\n stateManager,\n ...rest\n }: AcceptConnectionRequestToolParams) {\n super(rest);\n this.hcsClient = hcsClient;\n this.stateManager = stateManager;\n this.logger = Logger.getInstance({\n module: 'AcceptConnectionRequestTool',\n });\n }\n\n protected async _call({\n requestKey,\n hbarFee,\n exemptAccountIds,\n }: z.infer<this['schema']>): Promise<string> {\n const currentAgent = this.stateManager.getCurrentAgent();\n if (!currentAgent) {\n return 'Error: Cannot accept connection request. No agent is currently active. Please register or select an agent first.';\n }\n\n const connectionsManager = this.stateManager.getConnectionsManager();\n if (!connectionsManager) {\n return 'Error: ConnectionsManager not initialized';\n }\n\n await connectionsManager.fetchConnectionData(currentAgent.accountId);\n\n // Find the request with the matching unique key or fallback to sequence number\n const allRequests = [\n ...connectionsManager.getPendingRequests(),\n ...connectionsManager.getConnectionsNeedingConfirmation()\n ];\n\n const request = allRequests.find(\n (r) => (r.uniqueRequestKey === requestKey) ||\n (r.connectionRequestId?.toString() === requestKey) ||\n (r.inboundRequestId?.toString() === requestKey)\n );\n\n if (!request) {\n return `Error: Request with key ${requestKey} not found or no longer pending. Use the manage_connection_requests tool with action=\"list\" to verify.`;\n }\n\n // Get the numeric request ID from the request for the SDK call\n const numericRequestId = request.connectionRequestId || request.inboundRequestId;\n if (!numericRequestId) {\n return `Error: Could not determine a valid request ID for the request with key ${requestKey}.`;\n }\n\n try {\n const inboundTopicId = await this.hcsClient.getInboundTopicId();\n let feeConfigBuilder = undefined;\n\n if (hbarFee && hbarFee > 0) {\n const collectorId = this.hcsClient.getAccountAndSigner().accountId;\n try {\n feeConfigBuilder = new FeeConfigBuilder({\n network: this.hcsClient.getNetwork(),\n logger: this.logger,\n defaultCollectorAccountId: collectorId,\n });\n\n const finalExemptions = [\n ...(exemptAccountIds || []),\n currentAgent.accountId,\n ];\n feeConfigBuilder.addHbarFee(hbarFee, collectorId, finalExemptions);\n this.logger.info(\n `Setting HBAR fee: ${hbarFee} HBAR to be collected by ${collectorId}`\n );\n } catch (feeConfigError) {\n this.logger.error(\n `Error creating fee configuration: ${feeConfigError}`\n );\n\n feeConfigBuilder = undefined;\n this.logger.warn(\n 'Proceeding to accept request without fees due to configuration error.'\n );\n }\n }\n\n this.logger.info(\n `Attempting to accept request Key: ${requestKey} (ID: ${numericRequestId}) from ${request.targetAccountId}`\n );\n const result = await this.hcsClient.handleConnectionRequest(\n inboundTopicId,\n request.targetAccountId,\n numericRequestId,\n feeConfigBuilder\n );\n\n if (!result?.connectionTopicId) {\n return `Error: Failed to accept connection request with key ${requestKey}. The SDK did not return a connection topic ID.`;\n }\n this.logger.info(\n `Successfully created connection topic: ${result.connectionTopicId}`\n );\n\n const connectionTopicId = result.connectionTopicId;\n\n let targetInboundTopic = '';\n try {\n const targetProfileData = await this.hcsClient.standardClient.retrieveProfile(request.targetAccountId);\n targetInboundTopic =\n targetProfileData?.topicInfo?.inboundTopic || '';\n if (!targetInboundTopic) {\n this.logger.warn(\n `Could not resolve target inbound topic for ${request.targetAccountId}`\n );\n }\n } catch (e) {\n this.logger.warn(\n `Error fetching target profile/topic for ${request.targetAccountId}: ${e}`\n );\n }\n\n const name = request.profileInfo?.display_name || request.profileInfo?.alias || `Agent ${request.targetAccountId}`;\n const newConnection: ActiveConnection = {\n targetAccountId: request.targetAccountId,\n targetAgentName: name,\n targetInboundTopicId: targetInboundTopic,\n connectionTopicId,\n profileInfo: request.profileInfo,\n created: new Date(),\n status: 'established',\n };\n\n this.stateManager.addActiveConnection(newConnection);\n connectionsManager.fetchConnectionData(request.targetAccountId);\n\n this.logger.info(`Removed request ${requestKey} from pending requests`);\n\n let feeMessage = '';\n if (hbarFee && hbarFee > 0 && feeConfigBuilder) {\n feeMessage = ` with a ${hbarFee} HBAR fee per message`;\n }\n\n const displayKey = request.uniqueRequestKey || requestKey;\n return `Successfully accepted connection request ${displayKey} from ${name} ${feeMessage}. Connection established on topic: ${connectionTopicId}.`;\n } catch (error) {\n this.logger.error(\n `Error accepting connection request ${requestKey}: ${error}`\n );\n\n return `Error accepting connection request ${requestKey}: ${\n error instanceof Error ? error.message : String(error)\n }`;\n }\n }\n}\n","import { StructuredTool } from '@langchain/core/tools';\nimport { z } from 'zod';\nimport { HCS10Client } from '../hcs10/HCS10Client';\nimport { Logger } from '@hashgraphonline/standards-sdk';\n\n/**\n * Tool for retrieving the HCS-11 profile associated with a Hedera account ID.\n * Utilizes the HCS10Client's retrieveProfile method, which handles fetching.\n */\nexport class RetrieveProfileTool extends StructuredTool {\n name = 'retrieve_profile';\n description =\n 'Retrieves the HCS-11 profile data associated with a given Hedera account ID. If no account ID is provided, it defaults to the current operator account ID. Returns the profile object as a JSON string on success.';\n\n private client: HCS10Client;\n private logger: Logger;\n\n schema = z.object({\n accountId: z\n .string()\n .optional()\n .describe(\n 'The Hedera account ID (e.g., 0.0.12345) to retrieve the profile for. If omitted, defaults to the current operator account ID.'\n ),\n disableCache: z\n .boolean()\n .optional()\n .describe(\n 'Optional: Set to true to bypass the cache and fetch fresh profile data.'\n ),\n });\n\n /**\n * Creates a new RetrieveProfileTool instance.\n * @param client - An instance of HCS10Client.\n */\n constructor(client: HCS10Client) {\n super();\n this.client = client;\n this.logger = Logger.getInstance({ module: this.name });\n }\n\n /**\n * Executes the profile retrieval.\n * @param input - The input object containing accountId and optional disableCache flag.\n * @returns A JSON string of the profile on success, or an error message string.\n */\n async _call(input: z.infer<typeof this.schema>): Promise<string> {\n let targetAccountId: string;\n try {\n if (input.accountId) {\n targetAccountId = input.accountId;\n } else {\n this.logger.info('accountId not provided, defaulting to operator ID.');\n targetAccountId = this.client.getOperatorId();\n }\n\n if (!targetAccountId) {\n throw new Error('Could not determine target account ID.');\n }\n\n this.logger.info(\n `Attempting to retrieve profile for account: ${targetAccountId}, Disable Cache: ${!!input.disableCache}`\n );\n\n // Call retrieveProfile via the standardClient instance using the determined ID\n const result = await this.client.standardClient.retrieveProfile(\n targetAccountId,\n input.disableCache\n );\n\n if (result.success && result.profile) {\n this.logger.info(\n `Successfully retrieved profile for ${targetAccountId}.`\n );\n\n return JSON.stringify(result.profile, null, 2); \n } else {\n const errorMessage = `Error retrieving profile for ${targetAccountId}: ${\n result.error || 'Profile not found or invalid.'\n }`;\n this.logger.error(errorMessage);\n return errorMessage;\n }\n } catch (error) {\n const idForError = input.accountId || 'operator default';\n const errorMessage = `Unexpected error retrieving profile for ${idForError}: ${\n error instanceof Error ? error.message : String(error)\n }`;\n this.logger.error(errorMessage, error);\n return errorMessage;\n }\n }\n}\n","import { StructuredTool, ToolParams } from '@langchain/core/tools';\nimport { z } from 'zod';\nimport {\n IStateManager,\n} from '../state/state-types';\nimport { HCS10Client } from '../hcs10/HCS10Client';\nimport {\n Logger,\n Connection,\n} from '@hashgraphonline/standards-sdk';\n\n\ntype ListPendingRequestsToolParams = ToolParams & {\n hcsClient: HCS10Client;\n stateManager: IStateManager;\n};\n\nexport class ListUnapprovedConnectionRequestsTool extends StructuredTool {\n name = 'list_unapproved_connection_requests';\n description =\n 'Lists all connection requests that are not fully established, including incoming requests needing approval and outgoing requests waiting for confirmation.';\n schema = z.object({\n sortBy: z\n .enum(['time_asc', 'time_desc', 'name_asc', 'name_desc'])\n .optional()\n .describe(\n 'Optional sorting criteria for the requests list (default: time_desc, newest first)'\n ),\n limit: z\n .number()\n .optional()\n .describe(\n 'Optional limit on the number of requests to return (default: all)'\n ),\n });\n\n private hcsClient: HCS10Client;\n private stateManager: IStateManager;\n private logger: Logger;\n\n constructor({\n hcsClient,\n stateManager,\n ...rest\n }: ListPendingRequestsToolParams) {\n super(rest);\n this.hcsClient = hcsClient;\n this.stateManager = stateManager;\n this.logger = Logger.getInstance({\n module: 'ListPendingRequestsTool',\n level: 'debug',\n });\n }\n\n protected async _call({\n sortBy = 'time_desc',\n limit,\n }: z.infer<this['schema']>): Promise<string> {\n const currentAgent = this.stateManager.getCurrentAgent();\n if (!currentAgent) {\n return 'Error: Cannot list pending requests. No agent is currently active. Please register or select an agent first.';\n }\n\n try {\n const pendingRequests = await this.findAllPendingRequests();\n return this.formatRequestsList(pendingRequests, sortBy, limit);\n } catch (error) {\n this.logger.error(`Error in ${this.name}: ${error}`);\n return `Error listing pending requests: ${\n error instanceof Error ? error.message : String(error)\n }`;\n }\n }\n\n /**\n * Processes the connection connectionMap to find all requests\n * that are not fully established (incoming unapproved and outgoing pending).\n */\n private async findAllPendingRequests(): Promise<Connection[]> {\n const connectionsManager = this.stateManager.getConnectionsManager();\n if (!connectionsManager) {\n return [];\n }\n const currentAgent = this.stateManager.getCurrentAgent();\n if (!currentAgent) {\n return [];\n }\n\n await connectionsManager.fetchConnectionData(currentAgent.accountId);\n const pendingRequests = connectionsManager.getPendingRequests();\n const connectionsNeedingConfirmation = connectionsManager.getConnectionsNeedingConfirmation();\n\n return [...pendingRequests, ...connectionsNeedingConfirmation];\n }\n\n /**\n * Formats the list of pending requests for display.\n */\n private formatRequestsList(\n requests: Connection[],\n sortBy: string,\n limit?: number\n ): string {\n if (requests.length === 0) {\n return 'No pending connection requests found (incoming or outgoing).';\n }\n\n const sortedRequests = this.sortRequests(requests, sortBy);\n const limitedRequests = limit\n ? sortedRequests.slice(0, limit)\n : sortedRequests;\n\n let output = `Found ${requests.length} pending connection request(s):\\n\\n`;\n\n limitedRequests.forEach((request, index) => {\n const statusIndicator =\n request.status === 'needs_confirmation'\n ? '🟠 Incoming'\n : '⚪️ Outgoing';\n output += `${index + 1}. ${statusIndicator} - ID: ${request.uniqueRequestKey}\\n`;\n output += ` ${\n request.status === 'needs_confirmation' ? 'From:' : 'To: '\n } ${request.targetAgentName} (${request.targetAccountId})\\n`;\n output += ` Sent/Rcvd: ${request.created.toLocaleString()}\\n`;\n if (request.memo) {\n output += ` Memo: ${request.memo}\\n`;\n }\n if (request.profileInfo?.bio) {\n output += ` Bio: ${request.profileInfo.bio.substring(0, 100)}${\n request.profileInfo.bio.length > 100 ? '...' : ''\n }\\n`;\n }\n output += '\\n';\n });\n\n output +=\n 'Use related tools (manage_requests, accept_request) to handle these items.';\n return output;\n }\n\n /**\n * Sorts connection requests based on the specified criteria.\n */\n private sortRequests(\n requests: Connection[],\n sortBy: string\n ): Connection[] {\n const requestsCopy = [...requests];\n\n switch (sortBy) {\n case 'time_asc':\n return requestsCopy.sort(\n (a, b) => a.created.getTime() - b.created.getTime()\n );\n case 'time_desc':\n return requestsCopy.sort(\n (a, b) => b.created.getTime() - a.created.getTime()\n );\n case 'name_asc':\n return requestsCopy.sort((a, b) =>\n a.targetAgentName?.localeCompare(b?.targetAgentName || '') || 0\n );\n case 'name_desc':\n return requestsCopy.sort((a, b) =>\n b.targetAgentName?.localeCompare(a?.targetAgentName || '') || 0\n );\n default:\n return requestsCopy.sort(\n (a, b) => b.created.getTime() - a.created.getTime()\n );\n }\n }\n}\n","import {\n HCS10Client,\n AgentBuilder,\n Logger,\n} from '@hashgraphonline/standards-sdk';\nimport fs from 'fs';\nimport path from 'path';\nimport { ensureAgentHasEnoughHbar } from './ensure-agent-has-hbar';\n\nexport const ENV_FILE_PATH = path.join(process.cwd(), '.env');\n\nexport interface AgentData {\n accountId: string;\n operatorId: string;\n inboundTopicId: string;\n outboundTopicId: string;\n client: HCS10Client;\n}\n\nexport interface RegistrationProgressData {\n registered: boolean;\n accountId?: string;\n privateKey?: string;\n publicKey?: string;\n inboundTopicId?: string;\n outboundTopicId?: string;\n}\n\nexport async function getAgentFromEnv(\n logger: Logger,\n baseClient: HCS10Client,\n agentName: string,\n envPrefix: string\n): Promise<AgentData | null> {\n const accountIdEnvVar = `${envPrefix}_ACCOUNT_ID`;\n const privateKeyEnvVar = `${envPrefix}_PRIVATE_KEY`;\n const inboundTopicIdEnvVar = `${envPrefix}_INBOUND_TOPIC_ID`;\n const outboundTopicIdEnvVar = `${envPrefix}_OUTBOUND_TOPIC_ID`;\n\n const accountId = process.env[accountIdEnvVar];\n const privateKey = process.env[privateKeyEnvVar];\n const inboundTopicId = process.env[inboundTopicIdEnvVar];\n const outboundTopicId = process.env[outboundTopicIdEnvVar];\n\n if (!accountId || !privateKey || !inboundTopicId || !outboundTopicId) {\n logger.info(`${agentName} agent not found in environment variables`);\n return null;\n }\n\n logger.info(`${agentName} agent found in environment variables`);\n logger.info(`${agentName} account ID: ${accountId}`);\n logger.info(`${agentName} inbound topic ID: ${inboundTopicId}`);\n logger.info(`${agentName} outbound topic ID: ${outboundTopicId}`);\n\n const client = new HCS10Client({\n network: 'testnet',\n operatorId: accountId,\n operatorPrivateKey: privateKey,\n guardedRegistryBaseUrl: process.env.REGISTRY_URL,\n prettyPrint: true,\n logLevel: 'debug',\n });\n\n await ensureAgentHasEnoughHbar(logger, baseClient, accountId, agentName);\n\n return {\n accountId,\n operatorId: `${inboundTopicId}@${accountId}`,\n inboundTopicId,\n outboundTopicId,\n client,\n };\n}\n\nexport async function createAgent(\n logger: Logger,\n baseClient: HCS10Client,\n agentName: string,\n agentBuilder: AgentBuilder,\n envPrefix: string\n): Promise<AgentData | null> {\n try {\n logger.info(`Creating ${agentName} agent...`);\n\n const result = await baseClient.createAndRegisterAgent(agentBuilder);\n\n if (!result.metadata) {\n logger.error(`${agentName} agent creation failed`);\n return null;\n }\n\n logger.info(`${agentName} agent created successfully`);\n logger.info(`${agentName} account ID: ${result.metadata.accountId}`);\n logger.info(`${agentName} private key: ${result.metadata.privateKey}`);\n logger.info(\n `${agentName} inbound topic ID: ${result.metadata.inboundTopicId}`\n );\n logger.info(\n `${agentName} outbound topic ID: ${result.metadata.outboundTopicId}`\n );\n\n const envVars = {\n [`${envPrefix}_ACCOUNT_ID`]: result.metadata.accountId,\n [`${envPrefix}_PRIVATE_KEY`]: result.metadata.privateKey,\n [`${envPrefix}_INBOUND_TOPIC_ID`]: result.metadata.inboundTopicId,\n [`${envPrefix}_OUTBOUND_TOPIC_ID`]: result.metadata.outboundTopicId,\n };\n\n await updateEnvFile(ENV_FILE_PATH, envVars);\n\n const client = new HCS10Client({\n network: 'testnet',\n operatorId: result.metadata.accountId,\n operatorPrivateKey: result.metadata.privateKey,\n guardedRegistryBaseUrl: process.env.REGISTRY_URL,\n prettyPrint: true,\n logLevel: 'debug',\n });\n\n return {\n accountId: result.metadata.accountId,\n operatorId: `${result.metadata.inboundTopicId}@${result.metadata.accountId}`,\n inboundTopicId: result.metadata.inboundTopicId,\n outboundTopicId: result.metadata.outboundTopicId,\n client,\n };\n } catch (error) {\n console.log('error', error, baseClient);\n logger.error(`Error creating ${agentName} agent:`, error);\n return null;\n }\n}\n\nexport async function updateEnvFile(\n envFilePath: string,\n variables: Record<string, string>\n): Promise<void> {\n let envContent = '';\n\n if (fs.existsSync(envFilePath)) {\n envContent = fs.readFileSync(envFilePath, 'utf8');\n }\n\n const envLines = envContent.split('\\n');\n const updatedLines = [...envLines];\n\n for (const [key, value] of Object.entries(variables)) {\n const lineIndex = updatedLines.findIndex((line) =>\n line.startsWith(`${key}=`)\n );\n\n if (lineIndex !== -1) {\n updatedLines[lineIndex] = `${key}=${value}`;\n } else {\n updatedLines.push(`${key}=${value}`);\n }\n }\n\n fs.writeFileSync(envFilePath, updatedLines.join('\\n'));\n}\n","import { updateEnvFile } from '../utils/state-tools';\nimport {\n RegisteredAgent,\n ActiveConnection,\n IStateManager,\n AgentPersistenceOptions,\n EnvFilePersistenceOptions,\n ConnectionStatus,\n} from './state-types';\nimport {\n ConnectionsManager,\n HCS10BaseClient,\n Connection,\n Logger,\n IConnectionsManager,\n} from '@hashgraphonline/standards-sdk';\n\n/**\n * Implementation of the IStateManager interface for the OpenConvai system.\n * Manages agent state and connection information with thread safety and\n * proper timestamp tracking.\n */\nexport class OpenConvaiState implements IStateManager {\n private currentAgent: RegisteredAgent | null = null;\n private connectionMessageTimestamps: Record<string, number> = {};\n private defaultEnvFilePath?: string;\n private defaultPrefix: string;\n private connectionsManager: IConnectionsManager | null = null;\n private logger: Logger;\n\n /**\n * Creates a new OpenConvaiState instance\n * @param options - Options for environment variable persistence\n */\n constructor(options?: {\n defaultEnvFilePath?: string;\n defaultPrefix?: string;\n baseClient?: HCS10BaseClient;\n disableLogging?: boolean;\n }) {\n this.defaultEnvFilePath = options?.defaultEnvFilePath;\n this.defaultPrefix = options?.defaultPrefix ?? 'TODD';\n const shouldSilence = options?.disableLogging || process.env.DISABLE_LOGGING === 'true';\n this.logger = new Logger({ module: 'OpenConvaiState', silent: shouldSilence });\n\n // Initialize ConnectionsManager immediately if baseClient is provided\n if (options?.baseClient) {\n this.initializeConnectionsManager(options.baseClient);\n }\n }\n\n /**\n * Initializes the ConnectionsManager\n * @param baseClient - HCS10BaseClient instance to use\n */\n initializeConnectionsManager(\n baseClient: HCS10BaseClient\n ): IConnectionsManager {\n if (!this.connectionsManager) {\n this.logger.debug('Initializing ConnectionsManager');\n this.connectionsManager = new ConnectionsManager({\n baseClient,\n logLevel: 'error',\n });\n } else {\n this.logger.debug('ConnectionsManager already initialized');\n }\n return this.connectionsManager;\n }\n\n /**\n * Gets the ConnectionsManager instance\n * @returns The ConnectionsManager instance, or null if not initialized\n */\n getConnectionsManager(): IConnectionsManager | null {\n return this.connectionsManager;\n }\n\n /**\n * Sets the current active agent and clears any previous connection data.\n * This should be called when switching between agents.\n */\n setCurrentAgent(agent: RegisteredAgent | null): void {\n this.currentAgent = agent;\n this.connectionMessageTimestamps = {};\n\n // Clear connections manager when changing agents\n if (this.connectionsManager) {\n this.connectionsManager.clearAll();\n }\n }\n\n /**\n * Returns the currently active agent or null if none is set.\n */\n getCurrentAgent(): RegisteredAgent | null {\n return this.currentAgent;\n }\n\n /**\n * Adds a new connection to the active connections list.\n * Ensures no duplicates are added based on connectionTopicId.\n * Initializes timestamp tracking for the connection.\n */\n addActiveConnection(connection: ActiveConnection): void {\n if (!this.connectionsManager) {\n this.logger.error(\n 'ConnectionsManager not initialized. Call initializeConnectionsManager before adding connections.'\n );\n throw new Error(\n 'ConnectionsManager not initialized. Call initializeConnectionsManager before adding connections.'\n );\n }\n\n // Convert from ActiveConnection to Connection\n const sdkConnection: Connection = {\n connectionTopicId: connection.connectionTopicId,\n targetAccountId: connection.targetAccountId,\n targetAgentName: connection.targetAgentName,\n targetInboundTopicId: connection.targetInboundTopicId,\n status: this.convertConnectionStatus(connection.status || 'established'),\n isPending: connection.isPending || false,\n needsConfirmation: connection.needsConfirmation || false,\n created: connection.created || new Date(),\n lastActivity: connection.lastActivity,\n profileInfo: connection.profileInfo,\n connectionRequestId: connection.connectionRequestId,\n processed: true,\n };\n\n // Add to ConnectionsManager\n this.connectionsManager.updateOrAddConnection(sdkConnection);\n\n // Initialize timestamp tracking\n this.initializeTimestampIfNeeded(connection.connectionTopicId);\n }\n\n /**\n * Updates an existing connection or adds it if not found.\n * Preserves existing properties when updating by merging objects.\n */\n updateOrAddConnection(connection: ActiveConnection): void {\n this.addActiveConnection(connection);\n }\n\n /**\n * Returns a copy of all active connections.\n */\n listConnections(): ActiveConnection[] {\n if (!this.connectionsManager) {\n this.logger.debug(\n 'ConnectionsManager not initialized, returning empty connections list'\n );\n return [];\n }\n\n // Convert SDK Connections to ActiveConnection\n return this.connectionsManager\n .getAllConnections()\n .map((conn) => this.convertToActiveConnection(conn));\n }\n\n /**\n * Finds a connection by its identifier, which can be:\n * - A 1-based index as displayed in the connection list\n * - A target account ID string\n * - A connection topic ID string\n */\n getConnectionByIdentifier(identifier: string): ActiveConnection | undefined {\n if (!this.connectionsManager) {\n return undefined;\n }\n\n const connections = this.listConnections();\n\n // Check if it's a 1-based index\n const numericIndex = parseInt(identifier) - 1;\n if (\n !isNaN(numericIndex) &&\n numericIndex >= 0 &&\n numericIndex < connections.length\n ) {\n return connections[numericIndex];\n }\n\n // Check if it's a topic ID\n const byTopicId =\n this.connectionsManager.getConnectionByTopicId(identifier);\n if (byTopicId) {\n return this.convertToActiveConnection(byTopicId);\n }\n\n // Check if it's an account ID\n const byAccountId =\n this.connectionsManager.getConnectionByAccountId(identifier);\n if (byAccountId) {\n return this.convertToActiveConnection(byAccountId);\n }\n\n return undefined;\n }\n\n /**\n * Gets the last processed message timestamp for a connection.\n * Returns 0 if no timestamp has been recorded.\n */\n getLastTimestamp(connectionTopicId: string): number {\n return this.connectionMessageTimestamps[connectionTopicId] || 0;\n }\n\n /**\n * Updates the last processed message timestamp for a connection,\n * but only if the new timestamp is more recent than the existing one.\n */\n updateTimestamp(connectionTopicId: string, timestampNanos: number): void {\n // Initialize if this is first update and skip the comparison logic\n if (!(connectionTopicId in this.connectionMessageTimestamps)) {\n this.connectionMessageTimestamps[connectionTopicId] = timestampNanos;\n return;\n }\n\n // Otherwise, only update if newer\n const currentTimestamp =\n this.connectionMessageTimestamps[connectionTopicId];\n if (timestampNanos > currentTimestamp) {\n this.connectionMessageTimestamps[connectionTopicId] = timestampNanos;\n }\n }\n\n /**\n * Helper method to initialize timestamp tracking for a connection\n * if it doesn't already exist.\n */\n private initializeTimestampIfNeeded(connectionTopicId: string): void {\n if (!(connectionTopicId in this.connectionMessageTimestamps)) {\n this.connectionMessageTimestamps[connectionTopicId] =\n Date.now() * 1_000_000;\n }\n }\n\n /**\n * Converts ConnectionStatus to SDK status format\n */\n private convertConnectionStatus(\n status: string\n ): 'pending' | 'established' | 'needs_confirmation' | 'closed' {\n switch (status) {\n case 'pending':\n return 'pending';\n case 'established':\n return 'established';\n case 'needs confirmation':\n return 'needs_confirmation';\n default:\n return 'established';\n }\n }\n\n /**\n * Converts SDK Connection to ActiveConnection\n */\n private convertToActiveConnection(conn: Connection): ActiveConnection {\n return {\n targetAccountId: conn.targetAccountId,\n targetAgentName: conn.targetAgentName || `Agent ${conn.targetAccountId}`,\n targetInboundTopicId: conn.targetInboundTopicId || '',\n connectionTopicId: conn.connectionTopicId,\n status: this.convertToStateStatus(conn.status),\n created: conn.created,\n lastActivity: conn.lastActivity,\n isPending: conn.isPending,\n needsConfirmation: conn.needsConfirmation,\n profileInfo: conn.profileInfo,\n connectionRequestId: conn.connectionRequestId,\n };\n }\n\n /**\n * Converts SDK status to state status format\n */\n private convertToStateStatus(status: string): ConnectionStatus {\n switch (status) {\n case 'pending':\n return 'pending';\n case 'established':\n return 'established';\n case 'needs_confirmation':\n return 'needs confirmation';\n case 'closed':\n return 'established'; // Mapping closed to established for compatibility\n default:\n return 'unknown';\n }\n }\n\n /**\n * Persists agent data to environment variables\n * @param agent - The agent data to persist\n * @param options - Environment file persistence options\n */\n async persistAgentData(\n agent: RegisteredAgent,\n options?: AgentPersistenceOptions\n ): Promise<void> {\n if (options?.type && options.type !== 'env-file') {\n throw new Error(\n `Unsupported persistence type: ${options.type}. Only 'env-file' is supported.`\n );\n }\n\n const envFilePath =\n (options as EnvFilePersistenceOptions)?.envFilePath ||\n this.defaultEnvFilePath ||\n process.env.ENV_FILE_PATH ||\n '.env';\n\n if (!envFilePath) {\n throw new Error(\n 'Environment file path could not be determined for agent data persistence'\n );\n }\n\n const prefix =\n (options as EnvFilePersistenceOptions)?.prefix || this.defaultPrefix;\n\n if (!agent.accountId || !agent.inboundTopicId || !agent.outboundTopicId) {\n throw new Error('Agent data incomplete, cannot persist to environment');\n }\n\n const updates: Record<string, string> = {\n [`${prefix}_ACCOUNT_ID`]: agent.accountId,\n [`${prefix}_INBOUND_TOPIC_ID`]: agent.inboundTopicId,\n [`${prefix}_OUTBOUND_TOPIC_ID`]: agent.outboundTopicId,\n };\n\n if (agent.privateKey) {\n updates[`${prefix}_PRIVATE_KEY`] = agent.privateKey;\n }\n\n if (agent.profileTopicId) {\n updates[`${prefix}_PROFILE_TOPIC_ID`] = agent.profileTopicId;\n }\n\n await updateEnvFile(envFilePath, updates);\n }\n}\n","import { IPlugin, BasePluginContext } from './PluginInterface';\nimport { StructuredTool } from '@langchain/core/tools';\n\n/**\n * Base class for plugins to simplify implementation\n */\nexport abstract class BasePlugin<T extends BasePluginContext = BasePluginContext> implements IPlugin<T> {\n abstract id: string;\n abstract name: string;\n abstract description: string;\n abstract version: string;\n abstract author: string;\n\n protected context!: T;\n\n /**\n * Initialize the plugin with the provided context\n * @param context The context containing shared resources\n */\n async initialize(context: T): Promise<void> {\n this.context = context;\n }\n\n /**\n * Get the tools provided by this plugin\n * @returns Array of tools provided by this plugin\n */\n abstract getTools(): StructuredTool[];\n\n /**\n * Clean up resources when the plugin is unloaded\n * Default implementation does nothing\n */\n async cleanup(): Promise<void> {\n // Default implementation does nothing\n }\n}\n","import { StructuredTool } from '@langchain/core/tools';\nimport { z } from 'zod';\nimport { IPlugin /*, PluginContext */ } from '../PluginInterface';\nimport axios from 'axios'; // Use axios instead of node-fetch\n\nconst HEDERA_MIRROR_NODE_API = 'https://mainnet.mirrornode.hedera.com/api/v1';\n\n/**\n * Defines the schema for the HBAR price API response.\n */\nconst ExchangeRateResponseSchema = z.object({\n current_rate: z.object({\n cent_equivalent: z.number(),\n hbar_equivalent: z.number(),\n expiration_time: z.number(),\n }),\n next_rate: z.object({\n cent_equivalent: z.number(),\n hbar_equivalent: z.number(),\n expiration_time: z.number(),\n }),\n timestamp: z.string(),\n});\n\n/**\n * A Langchain tool to get the current HBAR price in USD.\n */\n// Export the class for testing purposes\nexport class GetHbarPriceTool extends StructuredTool {\n name = 'getHbarPrice';\n description = 'Retrieves the current price of HBAR in USD from the Hedera Mirror Node.';\n schema = z.object({}); // No input required for this tool\n\n /**\n * DISCLAIMER: THIS TOOL USES THE EXCHANGE RATE ENDPOINT FROM THE MIRROR NODE, AND IT IS NOT GUARANTEED TO BE ACCURATE.\n * USE AN ORACLE OR OTHER SOURCES FOR PRODUCTION USE WHERE PRICE IS IMPORTANT.\n * Retrieves the current price of HBAR in USD from the Hedera Mirror Node.\n * @returns A promise that resolves to a string containing the current HBAR price in USD.\n */\n protected async _call(): Promise<string> {\n try {\n // Use axios.get instead of fetch\n const response = await axios.get(`${HEDERA_MIRROR_NODE_API}/network/exchangerate`);\n\n // Axios puts data directly in response.data\n const data: unknown = response.data;\n\n // Validate the response structure\n const parsedData = ExchangeRateResponseSchema.safeParse(data);\n if (!parsedData.success) {\n console.error(\"Failed to parse exchange rate response:\", parsedData.error);\n throw new Error('Invalid API response format');\n }\n\n const { current_rate } = parsedData.data;\n const priceUsd = current_rate.cent_equivalent / current_rate.hbar_equivalent / 100;\n\n return `The current price of HBAR is $${priceUsd.toFixed(6)} USD.`;\n } catch (error) {\n console.error('Error fetching HBAR price:', error);\n // Handle axios errors specifically if needed, otherwise generic handling\n let errorMessage = 'An unknown error occurred';\n if (axios.isAxiosError(error)) {\n errorMessage = error.message;\n if (error.response) {\n errorMessage += ` (Status: ${error.response.status})`;\n }\n } else if (error instanceof Error) {\n errorMessage = error.message;\n }\n return `Failed to retrieve HBAR price: ${errorMessage}`;\n }\n }\n}\n\n\n/**\n * DISCLAIMER: THIS PLUGIN USES THE EXCHANGE RATE ENDPOINT FROM THE MIRROR NODE, AND IT IS NOT GUARANTEED TO BE ACCURATE.\n * USE AN ORACLE OR OTHER SOURCES FOR PRODUCTION USE WHERE PRICE IS IMPORTANT.\n * Plugin to provide tools related to Hedera network information, like HBAR price.\n */\nexport class HbarPricePlugin implements IPlugin {\n id = 'hedera-hbar-price';\n name = 'Hedera HBAR Price Plugin';\n description = 'Provides tools to interact with Hedera network data, specifically HBAR price.';\n version = '1.0.0';\n author = 'Hedera Agent'; // Replace with actual author/team name if desired\n\n private tools: StructuredTool[];\n\n constructor() {\n this.tools = [new GetHbarPriceTool()];\n }\n\n /**\n * Initializes the plugin. Currently no specific initialization needed.\n */\n async initialize(): Promise<void> {\n // No specific initialization required for this plugin yet\n return Promise.resolve();\n }\n\n /**\n * Returns the tools provided by this plugin.\n * @returns An array containing the GetHbarPriceTool.\n */\n getTools(): StructuredTool[] {\n return this.tools;\n }\n\n /**\n * Cleans up resources. Currently no cleanup needed.\n */\n async cleanup(): Promise<void> {\n // No cleanup necessary\n return Promise.resolve();\n }\n}","import { BasePlugin } from './BasePlugin';\nimport { GenericPluginContext } from './PluginInterface';\nimport { StructuredTool } from '@langchain/core/tools';\n\n/**\n * Base class for platform-agnostic plugins that can be used across different implementations\n */\nexport abstract class GenericPlugin extends BasePlugin<GenericPluginContext> {\n /**\n * Namespace for the plugin, used for organizing and categorizing plugins\n */\n abstract namespace: string;\n\n /**\n * Get the tools provided by this plugin\n * @returns Array of tools provided by this plugin\n */\n abstract override getTools(): StructuredTool[];\n}","import { BasePlugin } from './BasePlugin';\nimport { PluginContext } from './PluginInterface';\nimport { StructuredTool } from '@langchain/core/tools';\n\n/**\n * Base class for plugins that require HCS10 specific functionality\n */\nexport abstract class HCS10Plugin extends BasePlugin<PluginContext> {\n /**\n * Get the tools provided by this plugin\n * @returns Array of tools provided by this plugin\n */\n abstract override getTools(): StructuredTool[];\n}","import { GenericPlugin } from '../GenericPlugin';\nimport { GenericPluginContext } from '../PluginInterface';\nimport { StructuredTool } from '@langchain/core/tools';\nimport { HCS10Client } from '../../hcs10/HCS10Client';\nimport { IStateManager } from '../../state/state-types';\nimport { OpenConvaiState } from '../../state/open-convai-state';\n\nimport { RegisterAgentTool } from '../../tools/RegisterAgentTool';\nimport { SendMessageTool } from '../../tools/SendMessageTool';\nimport { ConnectionTool } from '../../tools/ConnectionTool';\nimport { FindRegistrationsTool } from '../../tools/FindRegistrationsTool';\nimport { InitiateConnectionTool } from '../../tools/InitiateConnectionTool';\nimport { ListConnectionsTool } from '../../tools/ListConnectionsTool';\nimport { SendMessageToConnectionTool } from '../../tools/SendMessageToConnectionTool';\nimport { CheckMessagesTool } from '../../tools/CheckMessagesTool';\nimport { ConnectionMonitorTool } from '../../tools/ConnectionMonitorTool';\nimport { ManageConnectionRequestsTool } from '../../tools/ManageConnectionRequestsTool';\nimport { AcceptConnectionRequestTool } from '../../tools/AcceptConnectionRequestTool';\nimport { RetrieveProfileTool } from '../../tools/RetrieveProfileTool';\nimport { ListUnapprovedConnectionRequestsTool } from '../../tools/ListUnapprovedConnectionRequestsTool';\n\n/**\n * OpenConvAI Plugin that provides all the tools from standards-agent-kit\n * This plugin enables full HCS-10 agent functionality including registration,\n * connection management, and messaging capabilities.\n */\nexport class OpenConvAIPlugin extends GenericPlugin {\n id = 'openconvai-standards-agent-kit';\n name = 'OpenConvAI Standards Agent Kit Plugin';\n description =\n 'Comprehensive plugin providing all HCS-10 agent tools for registration, connections, and messaging';\n version = '1.0.0';\n author = 'Hashgraph Online';\n namespace = 'openconvai';\n\n private hcs10Client?: HCS10Client;\n private stateManager?: IStateManager;\n private tools: StructuredTool[] = [];\n\n override async initialize(context: GenericPluginContext): Promise<void> {\n await super.initialize(context);\n\n if (!(context.client instanceof HCS10Client)) {\n throw new Error('OpenConvAIPlugin requires an HCS10Client instance');\n }\n\n this.hcs10Client = context.client as HCS10Client;\n\n this.stateManager =\n (context.stateManager as IStateManager) || new OpenConvaiState();\n\n this.initializeTools();\n\n this.context.logger.info(\n 'OpenConvAI Standards Agent Kit Plugin initialized successfully'\n );\n }\n\n private initializeTools(): void {\n if (!this.hcs10Client || !this.stateManager) {\n throw new Error(\n 'HCS10Client and StateManager must be initialized before creating tools'\n );\n }\n\n this.tools = [\n new RegisterAgentTool(this.hcs10Client, this.stateManager),\n new SendMessageTool(this.hcs10Client),\n new ConnectionTool({\n client: this.hcs10Client,\n stateManager: this.stateManager,\n }),\n new FindRegistrationsTool({\n hcsClient: this.hcs10Client,\n }),\n new RetrieveProfileTool(this.hcs10Client),\n new InitiateConnectionTool({\n hcsClient: this.hcs10Client,\n stateManager: this.stateManager,\n }),\n new ListConnectionsTool({\n hcsClient: this.hcs10Client,\n stateManager: this.stateManager,\n }),\n new SendMessageToConnectionTool({\n hcsClient: this.hcs10Client,\n stateManager: this.stateManager,\n }),\n new CheckMessagesTool({\n hcsClient: this.hcs10Client,\n stateManager: this.stateManager,\n }),\n new ConnectionMonitorTool({\n hcsClient: this.hcs10Client,\n stateManager: this.stateManager,\n }),\n new ManageConnectionRequestsTool({\n hcsClient: this.hcs10Client,\n stateManager: this.stateManager,\n }),\n new AcceptConnectionRequestTool({\n hcsClient: this.hcs10Client,\n stateManager: this.stateManager,\n }),\n new ListUnapprovedConnectionRequestsTool({\n stateManager: this.stateManager,\n hcsClient: this.hcs10Client,\n }),\n ];\n }\n\n getTools(): StructuredTool[] {\n return this.tools;\n }\n\n override async cleanup(): Promise<void> {\n this.tools = [];\n this.hcs10Client = undefined;\n this.stateManager = undefined;\n this.context.logger.info(\n 'OpenConvAI Standards Agent Kit Plugin cleaned up'\n );\n }\n}\n","import { PluginContext } from './PluginInterface';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { IPlugin } from './PluginInterface';\n\n/**\n * Configuration for loading a plugin\n */\nexport interface PluginLoadOptions {\n /**\n * Whether to initialize the plugin after loading\n * @default true\n */\n initialize?: boolean;\n}\n\n/**\n * Utility for loading plugins from different sources\n */\nexport class PluginLoader {\n /**\n * Load a plugin from a directory\n * @param directory Path to the directory containing the plugin\n * @param context Context to provide to the plugin during initialization\n * @param options Options for loading the plugin\n * @returns The loaded plugin instance\n */\n static async loadFromDirectory(\n directory: string,\n context: PluginContext,\n options: PluginLoadOptions = { initialize: true }\n ): Promise<IPlugin> {\n const manifestPath = path.join(directory, 'plugin.json');\n\n if (!fs.existsSync(manifestPath)) {\n throw new Error(`Plugin manifest not found at ${manifestPath}`);\n }\n\n try {\n const manifestContent = fs.readFileSync(manifestPath, 'utf8');\n const manifest = JSON.parse(manifestContent);\n\n // Validate manifest\n if (!manifest.id || !manifest.main) {\n throw new Error('Invalid plugin manifest: missing required fields (id, main)');\n }\n\n // Load the plugin module\n const mainPath = path.join(directory, manifest.main);\n if (!fs.existsSync(mainPath)) {\n throw new Error(`Plugin main file not found at ${mainPath}`);\n }\n\n // Import the plugin module\n const pluginModule = await import(mainPath);\n const PluginClass = pluginModule.default || pluginModule[manifest.id];\n\n if (!PluginClass) {\n throw new Error(`Could not find plugin class in ${mainPath}`);\n }\n\n // Create an instance of the plugin\n const plugin = new PluginClass();\n\n // Validate that it implements the IPlugin interface\n if (!this.isValidPlugin(plugin)) {\n throw new Error(`Plugin does not implement the IPlugin interface correctly`);\n }\n\n // Initialize the plugin if requested\n if (options.initialize) {\n await plugin.initialize(context);\n }\n\n return plugin;\n } catch (error) {\n throw new Error(`Failed to load plugin from directory ${directory}: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n\n /**\n * Load a plugin from an npm package\n * @param packageName Name of the npm package containing the plugin\n * @param context Context to provide to the plugin during initialization\n * @param options Options for loading the plugin\n * @returns The loaded plugin instance\n */\n static async loadFromPackage(\n packageName: string,\n context: PluginContext,\n options: PluginLoadOptions = { initialize: true }\n ): Promise<IPlugin> {\n try {\n // Resolve the package path\n const packagePath = require.resolve(packageName);\n const packageDir = path.dirname(packagePath);\n\n return this.loadFromDirectory(packageDir, context, options);\n } catch (error) {\n throw new Error(`Failed to load plugin from package ${packageName}: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n\n /**\n * Check if an object implements the IPlugin interface\n * @param obj Object to check\n * @returns true if the object implements IPlugin, false otherwise\n */\n private static isValidPlugin(obj: any): obj is IPlugin {\n return (\n obj &&\n typeof obj.id === 'string' &&\n typeof obj.name === 'string' &&\n typeof obj.description === 'string' &&\n typeof obj.version === 'string' &&\n typeof obj.author === 'string' &&\n typeof obj.initialize === 'function' &&\n typeof obj.getTools === 'function'\n );\n }\n}\n","import { IPlugin, PluginContext } from './PluginInterface';\nimport { StructuredTool } from '@langchain/core/tools';\nimport { Logger } from '@hashgraphonline/standards-sdk';\n\n/**\n * Registry for managing plugins in the Standards Agent Kit\n */\nexport class PluginRegistry {\n private plugins: Map<string, IPlugin> = new Map();\n private context: PluginContext;\n private logger: Logger;\n \n /**\n * Creates a new PluginRegistry instance\n * @param context The context to provide to plugins during initialization\n */\n constructor(context: PluginContext) {\n this.context = context;\n this.logger = context.logger;\n }\n \n /**\n * Register a plugin with the registry\n * @param plugin The plugin to register\n * @throws Error if a plugin with the same ID is already registered\n */\n async registerPlugin(plugin: IPlugin): Promise<void> {\n if (this.plugins.has(plugin.id)) {\n throw new Error(`Plugin with ID ${plugin.id} is already registered`);\n }\n \n await plugin.initialize(this.context);\n this.plugins.set(plugin.id, plugin);\n this.logger.info(`Plugin registered: ${plugin.name} (${plugin.id}) v${plugin.version}`);\n }\n \n /**\n * Get a plugin by ID\n * @param id The ID of the plugin to retrieve\n * @returns The plugin, or undefined if not found\n */\n getPlugin(id: string): IPlugin | undefined {\n return this.plugins.get(id);\n }\n \n /**\n * Get all registered plugins\n * @returns Array of all registered plugins\n */\n getAllPlugins(): IPlugin[] {\n return Array.from(this.plugins.values());\n }\n \n /**\n * Get all tools from all registered plugins\n * @returns Array of all tools provided by registered plugins\n */\n getAllTools(): StructuredTool[] {\n return this.getAllPlugins().flatMap(plugin => plugin.getTools());\n }\n \n /**\n * Unregister a plugin\n * @param id The ID of the plugin to unregister\n * @returns true if the plugin was unregistered, false if it wasn't found\n */\n async unregisterPlugin(id: string): Promise<boolean> {\n const plugin = this.plugins.get(id);\n if (!plugin) {\n return false;\n }\n \n if (plugin.cleanup) {\n try {\n await plugin.cleanup();\n } catch (error) {\n this.logger.error(`Error during plugin cleanup: ${error}`);\n }\n }\n \n const result = this.plugins.delete(id);\n if (result) {\n this.logger.info(`Plugin unregistered: ${plugin.name} (${plugin.id})`);\n }\n \n return result;\n }\n \n /**\n * Unregister all plugins\n */\n async unregisterAllPlugins(): Promise<void> {\n const pluginIds = Array.from(this.plugins.keys());\n for (const id of pluginIds) {\n await this.unregisterPlugin(id);\n }\n }\n}\n","import { HCS10Client, StandardNetworkType } from '../hcs10/HCS10Client';\nimport { RegisterAgentTool } from '../tools/RegisterAgentTool';\nimport { SendMessageTool } from '../tools/SendMessageTool';\nimport { ConnectionTool } from '../tools/ConnectionTool';\nimport { IStateManager } from '../state/state-types';\nimport { OpenConvaiState } from '../state/open-convai-state';\nimport { FindRegistrationsTool } from '../tools/FindRegistrationsTool';\nimport { InitiateConnectionTool } from '../tools/InitiateConnectionTool';\nimport { ListConnectionsTool } from '../tools/ListConnectionsTool';\nimport { SendMessageToConnectionTool } from '../tools/SendMessageToConnectionTool';\nimport { CheckMessagesTool } from '../tools/CheckMessagesTool';\nimport { ConnectionMonitorTool } from '../tools/ConnectionMonitorTool';\nimport { ManageConnectionRequestsTool } from '../tools/ManageConnectionRequestsTool';\nimport { AcceptConnectionRequestTool } from '../tools/AcceptConnectionRequestTool';\nimport { RetrieveProfileTool } from '../tools/RetrieveProfileTool';\nimport { ListUnapprovedConnectionRequestsTool } from '../tools/ListUnapprovedConnectionRequestsTool';\nimport { Logger } from '@hashgraphonline/standards-sdk';\nimport { ENV_FILE_PATH } from '../utils/state-tools';\n\nexport interface HCS10ClientConfig {\n operatorId?: string;\n operatorKey?: string;\n network?: StandardNetworkType;\n useEncryption?: boolean;\n registryUrl?: string;\n logLevel?: 'debug' | 'info' | 'warn' | 'error';\n}\n\nexport interface HCS10InitializationOptions {\n clientConfig?: HCS10ClientConfig;\n stateManager?: IStateManager;\n createAllTools?: boolean;\n monitoringClient?: boolean;\n}\n\n/**\n * Tool collection containing all available tools from the standards-agent-kit\n */\nexport interface HCS10Tools {\n registerAgentTool: RegisterAgentTool;\n findRegistrationsTool: FindRegistrationsTool;\n retrieveProfileTool: RetrieveProfileTool;\n initiateConnectionTool: InitiateConnectionTool;\n listConnectionsTool: ListConnectionsTool;\n sendMessageToConnectionTool: SendMessageToConnectionTool;\n checkMessagesTool: CheckMessagesTool;\n sendMessageTool: SendMessageTool;\n connectionTool: ConnectionTool;\n connectionMonitorTool: ConnectionMonitorTool;\n manageConnectionRequestsTool: ManageConnectionRequestsTool;\n acceptConnectionRequestTool: AcceptConnectionRequestTool;\n listUnapprovedConnectionRequestsTool: ListUnapprovedConnectionRequestsTool;\n}\n\n/**\n * Initializes the HCS10 client and returns pre-registered LangChain tools.\n *\n * @param options - Initialization options\n * @returns Object containing hcs10Client and requested tools\n */\nexport const initializeStandardsAgentKit = (\n options?: HCS10InitializationOptions\n): {\n hcs10Client: HCS10Client;\n monitoringClient?: HCS10Client;\n tools: Partial<HCS10Tools>;\n stateManager: IStateManager;\n} => {\n const config = options?.clientConfig || {};\n\n const operatorId = config.operatorId || process.env.HEDERA_OPERATOR_ID;\n const operatorPrivateKey =\n config.operatorKey || process.env.HEDERA_OPERATOR_KEY;\n\n const networkEnv = config.network || process.env.HEDERA_NETWORK || 'testnet';\n\n let network: StandardNetworkType;\n if (networkEnv === 'mainnet') {\n network = 'mainnet';\n } else if (networkEnv === 'testnet') {\n network = 'testnet';\n } else {\n console.warn(\n `Unsupported network specified: '${networkEnv}'. Defaulting to 'testnet'.`\n );\n network = 'testnet';\n }\n\n if (!operatorId || !operatorPrivateKey) {\n throw new Error(\n 'Operator ID and private key must be provided either through options or environment variables.'\n );\n }\n\n const shouldSilence = process.env.DISABLE_LOGGING === 'true';\n const logger = Logger.getInstance({\n level: config.logLevel || 'info',\n silent: shouldSilence,\n });\n\n const stateManager =\n options?.stateManager ||\n new OpenConvaiState({\n defaultEnvFilePath: ENV_FILE_PATH,\n defaultPrefix: 'TODD',\n });\n logger.info('State manager initialized');\n\n const hcs10Client = new HCS10Client(operatorId, operatorPrivateKey, network, {\n useEncryption: config.useEncryption,\n registryUrl: config.registryUrl,\n });\n logger.info(`HCS10Client initialized for ${operatorId} on ${network}`);\n\n let monitoringClient: HCS10Client | undefined;\n if (options?.monitoringClient) {\n monitoringClient = new HCS10Client(\n operatorId,\n operatorPrivateKey,\n network,\n {\n useEncryption: config.useEncryption,\n registryUrl: config.registryUrl,\n logLevel: 'error',\n }\n );\n logger.info('Monitoring client initialized');\n }\n\n const tools: Partial<HCS10Tools> = {};\n\n tools.registerAgentTool = new RegisterAgentTool(hcs10Client, stateManager);\n tools.sendMessageTool = new SendMessageTool(hcs10Client);\n tools.connectionTool = new ConnectionTool({\n client: monitoringClient || hcs10Client,\n stateManager,\n });\n\n if (options?.createAllTools) {\n tools.findRegistrationsTool = new FindRegistrationsTool({\n hcsClient: hcs10Client,\n });\n tools.retrieveProfileTool = new RetrieveProfileTool(hcs10Client);\n tools.initiateConnectionTool = new InitiateConnectionTool({\n hcsClient: hcs10Client,\n stateManager,\n });\n tools.listConnectionsTool = new ListConnectionsTool({\n hcsClient: hcs10Client,\n stateManager,\n });\n tools.sendMessageToConnectionTool = new SendMessageToConnectionTool({\n hcsClient: hcs10Client,\n stateManager,\n });\n tools.checkMessagesTool = new CheckMessagesTool({\n hcsClient: hcs10Client,\n stateManager,\n });\n tools.connectionMonitorTool = new ConnectionMonitorTool({\n hcsClient: monitoringClient || hcs10Client,\n stateManager,\n });\n tools.manageConnectionRequestsTool = new ManageConnectionRequestsTool({\n hcsClient: hcs10Client,\n stateManager,\n });\n tools.acceptConnectionRequestTool = new AcceptConnectionRequestTool({\n hcsClient: hcs10Client,\n stateManager,\n });\n tools.listUnapprovedConnectionRequestsTool =\n new ListUnapprovedConnectionRequestsTool({\n stateManager,\n hcsClient: hcs10Client,\n });\n\n logger.info('All tools initialized');\n }\n\n return {\n hcs10Client,\n monitoringClient,\n tools,\n stateManager,\n };\n};\n"],"names":["HCS10Client","constructor","operatorId","operatorPrivateKey","network","options","this","standardClient","StandardSDKClient","guardedRegistryBaseUrl","registryUrl","logLevel","useEncryption","shouldSilence","process","env","DISABLE_LOGGING","logger","Logger","level","silent","getOperatorId","operator","getClient","operatorAccountId","Error","toString","getNetwork","handleConnectionRequest","inboundTopicId","requestingAccountId","connectionRequestId","feeConfig","error","message","String","getAgentProfile","accountId","retrieveProfile","submitConnectionRequest","memo","waitForConnectionConfirmation","outboundTopicId","maxAttempts","delayMs","createAndRegisterAgent","metadata","builder","AgentBuilder","setName","name","setBio","description","setCapabilities","capabilities","StandardAIAgentCapability","TEXT_GENERATION","setType","type","setModel","model","setNetwork","setInboundTopicType","StandardInboundTopicType","PUBLIC","FEE_BASED","setFeeConfig","pfpBuffer","pfpFileName","byteLength","warn","info","setProfilePicture","social","Object","entries","forEach","platform","handle","addSocial","properties","key","value","addProperty","hasFees","Boolean","result","initialBalance","agentChannels","sendMessage","topicId","data","submitKey","messageResponse","topicSequenceNumber","toNumber","getMessages","mappedMessages","messages","map","sdkMessage","timestamp","created","getTime","sequence_number","sort","a","b","getMessageStream","getMessageContent","inscriptionIdOrData","getInboundTopicId","profileResponse","success","topicInfo","inboundTopic","detailedMessage","includes","getAccountAndSigner","signer","getOutboundTopicId","profile","outboundTopic","setClient","privateKey","validateOperator","isValid","initializeWithValidation","validationResult","stateManager","initializeConnectionsManager","RegisterAgentTool","StructuredTool","client","super","schema","z","object","string","describe","optional","enum","array","number","profilePicture","union","url","filename","path","feeCollectorAccountId","hbarFee","tokenFee","amount","tokenId","hbarFees","collectorAccount","tokenFees","exemptAccountIds","setAsCurrent","boolean","persistence","prefix","loadProfilePicture","getInstance","startsWith","response","axios","get","responseType","buffer","globalThis","Buffer","from","urlPathname","URL","pathname","basename","fs","existsSync","readFileSync","_call","input","AIAgentCapability","profilePictureSource","profilePictureData","hasHbarFee","hasTokenFee","hasValidTokenFee","hasHbarFees","length","hasTokenFees","collectorId","feeConfigBuilder","FeeConfigBuilder","filter","id","updatedFeeConfig","addHbarFee","fee","feeCollector","addTokenFee","processRegistrationResult","trim","newAgentAccountId","profileTopicId","pfpTopicId","validateRegistrationResult","agent","setCurrentAgent","persistAgentData","persistenceOptions","ensureAgentHasFunds","feeDescription","createFeeDescription","feeMessage","registrationDetails","source","JSON","stringify","agentName","async","baseClient","hbarBalance","requestAccount","balance","mirrorNode","HederaMirrorNode","hbarPrice","getHBARPrice","Date","balanceInUsd","toFixed","funder","targetHbar","amountToTransferHbar","Math","max","transferTx","TransferTransaction","addHbarTransfer","Hbar","fromTinybars","round","fundTxResponse","execute","getReceipt","fundingError","ensureAgentHasEnoughHbar","module","missingFields","join","tokenFeeText","SendMessageTool","lastProcessedTimestamp","disableMonitoring","monitorResponses","sequenceNumber","attempts","content","parsedContent","parse","Promise","resolve","setTimeout","ConnectionTool","rest","isMonitoring","monitoringTopic","errorMsg","monitorIncomingRequests","catch","lastProcessedMessageSequence","processedRequestIds","Set","allMessages","connectionRequests","msg","op","some","m","connection_id","debug","senderOperatorId","operator_id","split","has","confirmation","add","connectionTopicId","newConnection","targetAccountId","targetAgentName","targetInboundTopicId","addActiveConnection","handleError","stopMonitoring","SendMessageToConnectionTool","hcsClient","targetIdentifier","default","currentAgent","getCurrentAgent","connection","getConnectionByIdentifier","replyBack","InitiateConnectionTool","targetProfile","requestResult","sequenceNumberLong","isNaN","conversionError","confirmationTimeoutMs","ceil","confirmationResult","connections","listConnections","addedEntry","find","c","localConnectionId","indexOf","ListConnectionsTool","includeDetails","showPending","args","getEnhancedConnections","activeConnections","status","pendingConnections","isPending","needsConfirmation","output","conn","index","formatConnection","profileInfo","display_name","bio","substring","toLocaleString","lastActivity","connectionManager","getConnectionsManager","fetchConnectionData","updateOrAddConnection","console","CheckMessagesTool","fetchLatest","lastMessagesCount","int","positive","getLastTimestamp","messagesToProcess","latestTimestampNanos","isFetchingLatest","count","slice","reduce","maxTs","outputString","displayContent","parsed","p","parseError","updateTimestamp","FindRegistrationsTool","tags","nativeEnum","findRegistrations","registrations","reg","alias","createdAt","ConnectionMonitorTool","acceptAll","monitorDurationSeconds","defaultCollectorAccount","listConnectionsTool","updateClient","newClient","createFeeConfig","endTime","now","pollIntervalMs","lastSequenceNumber","connectionRequestsFound","acceptedConnections","skippedRequests","invoke","currentConnections","connectionsByAccountAndRequest","Map","set","newMessages","request","requestId","connectionsManager","isConnectionRequestProcessed","requestorAccountId","extractAccountId","markConnectionRequestProcessed","existingAccountConnections","acceptConnectionRequest","formatFeeString","agentAccountId","defaultCollector","defaultCollectorAccountId","exemptIds","push","collector","extractAccountFromOperatorId","profileError","feeString","hbarFeeDetails","tokenFeeDetails","update","ManageConnectionRequestsTool","action","requestKey","lastRefreshTime","refreshIntervalMs","refreshRequestsIfNeeded","listRequests","viewRequest","rejectRequest","refreshRequests","allRequests","getPendingRequests","getConnectionsNeedingConfirmation","log","requestType","requestIdDisplay","uniqueRequestKey","inboundRequestId","r","uniqueKey","originTopicId","AcceptConnectionRequestTool","numericRequestId","finalExemptions","feeConfigError","targetInboundTopic","targetProfileData","e","RetrieveProfileTool","disableCache","errorMessage","ListUnapprovedConnectionRequestsTool","sortBy","limit","pendingRequests","findAllPendingRequests","formatRequestsList","requests","sortedRequests","sortRequests","limitedRequests","statusIndicator","requestsCopy","localeCompare","ENV_FILE_PATH","cwd","OpenConvaiState","connectionMessageTimestamps","defaultEnvFilePath","defaultPrefix","disableLogging","ConnectionsManager","clearAll","sdkConnection","convertConnectionStatus","processed","initializeTimestampIfNeeded","getAllConnections","convertToActiveConnection","identifier","numericIndex","parseInt","byTopicId","getConnectionByTopicId","byAccountId","getConnectionByAccountId","timestampNanos","convertToStateStatus","envFilePath","updates","variables","envContent","updatedLines","lineIndex","findIndex","line","writeFileSync","updateEnvFile","BasePlugin","initialize","context","cleanup","ExchangeRateResponseSchema","current_rate","cent_equivalent","hbar_equivalent","expiration_time","next_rate","GetHbarPriceTool","arguments","parsedData","safeParse","isAxiosError","GenericPlugin","version","author","tools","getTools","namespace","hcs10Client","initializeTools","loadFromDirectory","directory","manifestPath","manifestContent","manifest","main","mainPath","pluginModule","import","PluginClass","plugin","isValidPlugin","loadFromPackage","packageName","packagePath","require","packageDir","dirname","obj","plugins","registerPlugin","getPlugin","getAllPlugins","Array","values","getAllTools","flatMap","unregisterPlugin","delete","unregisterAllPlugins","pluginIds","keys","config","clientConfig","HEDERA_OPERATOR_ID","operatorKey","HEDERA_OPERATOR_KEY","networkEnv","HEDERA_NETWORK","monitoringClient","registerAgentTool","sendMessageTool","connectionTool","createAllTools","findRegistrationsTool","retrieveProfileTool","initiateConnectionTool","sendMessageToConnectionTool","checkMessagesTool","connectionMonitorTool","manageConnectionRequestsTool","acceptConnectionRequestTool","listUnapprovedConnectionRequestsTool"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"standards-agent-kit.cjs","sources":["../../src/hcs10/HCS10Client.ts","../../src/tools/RegisterAgentTool.ts","../../src/utils/ensure-agent-has-hbar.ts","../../src/tools/SendMessageTool.ts","../../src/tools/ConnectionTool.ts","../../src/tools/SendMessageToConnectionTool.ts","../../src/tools/InitiateConnectionTool.ts","../../src/tools/ListConnectionsTool.ts","../../src/tools/CheckMessagesTool.ts","../../src/tools/FindRegistrationsTool.ts","../../src/tools/ConnectionMonitorTool.ts","../../src/tools/ManageConnectionRequestsTool.ts","../../src/tools/AcceptConnectionRequestTool.ts","../../src/tools/RetrieveProfileTool.ts","../../src/tools/ListUnapprovedConnectionRequestsTool.ts","../../src/utils/state-tools.ts","../../src/state/open-convai-state.ts","../../src/plugins/BasePlugin.ts","../../src/plugins/hedera/HbarPricePlugin.ts","../../src/plugins/GenericPlugin.ts","../../src/plugins/HCS10Plugin.ts","../../src/plugins/openconvai/OpenConvAIPlugin.ts","../../src/plugins/PluginLoader.ts","../../src/plugins/PluginRegistry.ts","../../src/init/init.ts"],"sourcesContent":["import { TransactionReceipt, PrivateKey } from '@hashgraph/sdk';\nimport {\n HCS10Client as StandardSDKClient,\n AgentBuilder,\n InboundTopicType as StandardInboundTopicType,\n AIAgentCapability as StandardAIAgentCapability,\n AgentRegistrationResult,\n WaitForConnectionConfirmationResponse,\n ProfileResponse as SDKProfileResponse,\n HCSMessage,\n LogLevel,\n Logger,\n FeeConfigBuilderInterface,\n SocialPlatform,\n} from '@hashgraphonline/standards-sdk';\nimport { AgentMetadata, AgentChannels } from './types';\nimport { encryptMessage } from '../utils/Encryption';\nimport { IStateManager } from '../state/state-types';\n\n// Keep type alias as they were removed accidentally\ntype StandardHandleConnectionRequest = InstanceType<\n typeof StandardSDKClient\n>['handleConnectionRequest'];\ntype HandleConnectionRequestResponse = Awaited<\n ReturnType<StandardHandleConnectionRequest>\n>;\nexport type StandardNetworkType = 'mainnet' | 'testnet';\n\nexport interface ClientValidationOptions {\n accountId: string;\n privateKey: string;\n network?: StandardNetworkType;\n stateManager?: IStateManager;\n}\n\nexport interface HCSMessageWithTimestamp extends HCSMessage {\n timestamp: number;\n data?: string;\n sequence_number: number;\n}\n\nexport interface ExtendedAgentMetadata extends AgentMetadata {\n pfpBuffer?: Buffer;\n pfpFileName?: string;\n feeConfig?: FeeConfigBuilderInterface;\n}\n\n/**\n * HCS10Client wraps the HCS-10 functionalities using the @hashgraphonline/standards-sdk.\n * - Creates and registers agents using the standard SDK flow.\n * - Manages agent communication channels (handled by standard SDK).\n * - Sends messages on Hedera topics (currently manual, potential for standard SDK integration).\n */\nexport class HCS10Client {\n public standardClient: StandardSDKClient;\n private useEncryption: boolean;\n public agentChannels?: AgentChannels;\n public guardedRegistryBaseUrl: string;\n public logger: Logger;\n\n constructor(\n operatorId: string,\n operatorPrivateKey: string,\n network: StandardNetworkType,\n options?: {\n useEncryption?: boolean;\n registryUrl?: string;\n logLevel?: LogLevel;\n }\n ) {\n this.standardClient = new StandardSDKClient({\n network: network,\n operatorId: operatorId,\n operatorPrivateKey: operatorPrivateKey,\n guardedRegistryBaseUrl: options?.registryUrl,\n logLevel: options?.logLevel,\n });\n this.guardedRegistryBaseUrl = options?.registryUrl || '';\n this.useEncryption = options?.useEncryption || false;\n const shouldSilence = process.env.DISABLE_LOGGING === 'true';\n this.logger = new Logger({\n level: options?.logLevel || 'info',\n silent: shouldSilence,\n });\n }\n\n public getOperatorId(): string {\n const operator = this.standardClient.getClient().operatorAccountId;\n if (!operator) {\n throw new Error('Operator Account ID not configured in standard client.');\n }\n return operator.toString();\n }\n\n public getNetwork(): StandardNetworkType {\n return this.standardClient.getNetwork() as StandardNetworkType;\n }\n\n public async handleConnectionRequest(\n inboundTopicId: string,\n requestingAccountId: string,\n connectionRequestId: number,\n feeConfig?: FeeConfigBuilderInterface\n ): Promise<HandleConnectionRequestResponse> {\n try {\n const result = await this.standardClient.handleConnectionRequest(\n inboundTopicId,\n requestingAccountId,\n connectionRequestId,\n feeConfig\n );\n return result;\n } catch (error) {\n this.logger.error(\n `Error handling connection request #${connectionRequestId} for topic ${inboundTopicId}:`,\n error\n );\n throw new Error(\n `Failed to handle connection request: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n /**\n * Retrieves the profile for a given account ID using the standard SDK.\n */\n public async getAgentProfile(accountId: string): Promise<SDKProfileResponse> {\n return this.standardClient.retrieveProfile(accountId);\n }\n\n /**\n * Exposes the standard SDK's submitConnectionRequest method.\n */\n public async submitConnectionRequest(\n inboundTopicId: string,\n memo: string\n ): Promise<TransactionReceipt> {\n return this.standardClient.submitConnectionRequest(\n inboundTopicId,\n memo\n ) as Promise<TransactionReceipt>;\n }\n\n /**\n * Exposes the standard SDK's waitForConnectionConfirmation method.\n */\n public async waitForConnectionConfirmation(\n outboundTopicId: string,\n connectionRequestId: number,\n maxAttempts = 60,\n delayMs = 2000\n ): Promise<WaitForConnectionConfirmationResponse> {\n return this.standardClient.waitForConnectionConfirmation(\n outboundTopicId,\n connectionRequestId,\n maxAttempts,\n delayMs\n );\n }\n\n /**\n * Creates and registers an agent using the standard SDK's HCS10Client.\n * This handles account creation, key generation, topic setup, and registration.\n *\n * When metadata includes fee configuration:\n * 1. The properties.feeConfig will be passed to the AgentBuilder\n * 2. The properties.inboundTopicType will be set to FEE_BASED\n * 3. The SDK's createAndRegisterAgent will apply the fees to the agent's inbound topic\n *\n * @param metadata - The agent's metadata, potentially including pfpBuffer, pfpFileName,\n * and fee configuration in properties.feeConfig\n * @returns The registration result from the standard SDK, containing accountId, keys, topics etc.\n */\n public async createAndRegisterAgent(\n metadata: ExtendedAgentMetadata\n ): Promise<AgentRegistrationResult> {\n const builder = new AgentBuilder()\n .setName(metadata.name)\n .setBio(metadata.description || '')\n .setCapabilities(\n metadata.capabilities\n ? metadata.capabilities\n : [StandardAIAgentCapability.TEXT_GENERATION]\n )\n .setType((metadata.type || 'autonomous') as 'autonomous' | 'manual')\n .setModel(metadata.model || 'agent-model-2024')\n .setNetwork(this.getNetwork())\n .setInboundTopicType(StandardInboundTopicType.PUBLIC);\n\n if (metadata?.feeConfig) {\n builder.setInboundTopicType(StandardInboundTopicType.FEE_BASED);\n builder.setFeeConfig(metadata.feeConfig);\n }\n\n if (metadata.pfpBuffer && metadata.pfpFileName) {\n if (metadata.pfpBuffer.byteLength === 0) {\n this.logger.warn(\n 'Provided PFP buffer is empty. Skipping profile picture.'\n );\n } else {\n this.logger.info(\n `Setting profile picture: ${metadata.pfpFileName} (${metadata.pfpBuffer.byteLength} bytes)`\n );\n builder.setProfilePicture(metadata.pfpBuffer, metadata.pfpFileName);\n }\n } else {\n this.logger.warn(\n 'Profile picture not provided in metadata. Agent creation might fail if required by the underlying SDK builder.'\n );\n }\n\n if (metadata.social) {\n Object.entries(metadata.social).forEach(([platform, handle]) => {\n builder.addSocial(platform as SocialPlatform, handle);\n });\n }\n\n if (metadata.properties) {\n Object.entries(metadata.properties).forEach(([key, value]) => {\n builder.addProperty(key, value);\n });\n }\n\n try {\n const hasFees = Boolean(metadata?.feeConfig);\n const result = await this.standardClient.createAndRegisterAgent(builder, {\n initialBalance: hasFees ? 50 : undefined,\n });\n if (\n result?.metadata?.inboundTopicId &&\n result?.metadata?.outboundTopicId\n ) {\n this.agentChannels = {\n inboundTopicId: result.metadata.inboundTopicId,\n outboundTopicId: result.metadata.outboundTopicId,\n };\n }\n return result;\n } catch (error) {\n this.logger.error('Error during agent creation/registration:', error);\n throw new Error(\n `Failed to create/register agent: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n /**\n * Sends a structured HCS-10 message to the specified topic using the standard SDK client.\n * Handles potential inscription for large messages.\n *\n * @param topicId - The target topic ID (likely a connection topic).\n * @param operatorId - The operator ID string (e.g., \"inboundTopic@accountId\").\n * @param data - The actual message content/data.\n * @param memo - Optional memo for the message.\n * @param submitKey - Optional private key for topics requiring specific submit keys.\n * @returns A confirmation status string from the transaction receipt.\n */\n public async sendMessage(\n topicId: string,\n data: string,\n memo?: string,\n submitKey?: PrivateKey\n ): Promise<number | undefined> {\n if (this.useEncryption) {\n data = encryptMessage(data);\n }\n\n try {\n const messageResponse = await this.standardClient.sendMessage(\n topicId,\n data,\n memo,\n submitKey\n );\n return messageResponse.topicSequenceNumber?.toNumber();\n } catch (error) {\n this.logger.error(`Error sending message to topic ${topicId}:`, error);\n throw new Error(\n `Failed to send message: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n /**\n * Retrieves messages from a topic using the standard SDK client.\n *\n * @param topicId - The topic ID to get messages from.\n * @returns Messages from the topic, mapped to the expected format.\n */\n public async getMessages(topicId: string): Promise<{\n messages: HCSMessageWithTimestamp[];\n }> {\n try {\n const result = await this.standardClient.getMessages(topicId);\n\n const mappedMessages = result.messages.map((sdkMessage) => {\n const timestamp = sdkMessage?.created?.getTime() || 0;\n\n return {\n ...sdkMessage,\n timestamp: timestamp,\n data: sdkMessage.data,\n sequence_number: sdkMessage.sequence_number,\n };\n });\n mappedMessages.sort(\n (a: { timestamp: number }, b: { timestamp: number }) =>\n a.timestamp - b.timestamp\n );\n return { messages: mappedMessages };\n } catch (error) {\n this.logger.error(`Error getting messages from topic ${topicId}:`, error);\n return { messages: [] };\n }\n }\n\n public async getMessageStream(topicId: string): Promise<{\n messages: HCSMessage[];\n }> {\n return this.standardClient.getMessageStream(topicId);\n }\n\n /**\n * Retrieves content from an inscribed message using the standard SDK client.\n * @param inscriptionIdOrData - The inscription ID (hcs://...) or potentially raw data string.\n * @returns The resolved message content.\n */\n public async getMessageContent(inscriptionIdOrData: string): Promise<string> {\n try {\n const content = await this.standardClient.getMessageContent(\n inscriptionIdOrData\n );\n return content as string;\n } catch (error) {\n this.logger.error(\n `Error retrieving message content for: ${inscriptionIdOrData}`,\n error\n );\n throw new Error(\n `Failed to retrieve message content: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n /**\n * Retrieves the inbound topic ID associated with the current operator.\n * This typically involves fetching the operator's own HCS-10 profile.\n * @returns A promise that resolves to the operator's inbound topic ID.\n * @throws {Error} If the operator ID cannot be determined or the profile/topic cannot be retrieved.\n */\n public async getInboundTopicId(): Promise<string> {\n try {\n const operatorId = this.getOperatorId();\n this.logger.info(\n `[HCS10Client] Retrieving profile for operator ${operatorId} to find inbound topic...`\n );\n const profileResponse = await this.getAgentProfile(operatorId);\n if (profileResponse.success && profileResponse.topicInfo?.inboundTopic) {\n this.logger.info(\n `[HCS10Client] Found inbound topic for operator ${operatorId}: ${profileResponse.topicInfo.inboundTopic}`\n );\n return profileResponse.topicInfo.inboundTopic;\n } else {\n throw new Error(\n `Could not retrieve inbound topic from profile for ${operatorId}. Profile success: ${profileResponse.success}, Error: ${profileResponse.error}`\n );\n }\n } catch (error) {\n this.logger.error(\n `[HCS10Client] Error fetching operator's inbound topic ID (${this.getOperatorId()}):`,\n error\n );\n const operatorId = this.getOperatorId();\n let detailedMessage = `Failed to get inbound topic ID for operator ${operatorId}.`;\n if (\n error instanceof Error &&\n error.message.includes('does not have a valid HCS-11 memo')\n ) {\n detailedMessage += ` The account profile may not exist or is invalid. Please ensure this operator account (${operatorId}) is registered as an HCS-10 agent. You might need to register it first (e.g., using the 'register_agent' tool or SDK function).`;\n } else if (error instanceof Error) {\n detailedMessage += ` Reason: ${error.message}`;\n } else {\n detailedMessage += ` Unexpected error: ${String(error)}`;\n }\n throw new Error(detailedMessage);\n }\n }\n\n /**\n * Retrieves the configured operator account ID and private key.\n * Required by tools needing to identify the current agent instance.\n */\n public getAccountAndSigner(): { accountId: string; signer: PrivateKey } {\n const result = this.standardClient.getAccountAndSigner();\n return {\n accountId: result.accountId,\n signer: result.signer as unknown as PrivateKey,\n };\n }\n\n /**\n * Retrieves the outbound topic ID for the current operator.\n * Fetches the operator's profile if necessary.\n * @returns The outbound topic ID string.\n * @throws If the outbound topic cannot be determined.\n */\n public async getOutboundTopicId(): Promise<string> {\n const operatorId = this.getOperatorId();\n const profile = await this.getAgentProfile(operatorId);\n if (profile.success && profile.topicInfo?.outboundTopic) {\n return profile.topicInfo.outboundTopic;\n } else {\n throw new Error(\n `Could not retrieve outbound topic from profile for ${operatorId}. Profile success: ${profile.success}, Error: ${profile.error}`\n );\n }\n }\n\n public setClient(accountId: string, privateKey: string): StandardSDKClient {\n this.standardClient = new StandardSDKClient({\n network: this.getNetwork(),\n operatorId: accountId,\n operatorPrivateKey: privateKey,\n guardedRegistryBaseUrl: this.guardedRegistryBaseUrl,\n });\n return this.standardClient;\n }\n\n /**\n * Validates that the operator account exists and has proper access for agent operations\n */\n private async validateOperator(options: ClientValidationOptions): Promise<{\n isValid: boolean;\n operator?: { accountId: string };\n error?: string;\n }> {\n try {\n // Set up client with provided operator details\n this.setClient(options.accountId, options.privateKey);\n\n // Check if we can retrieve the operator ID\n const operatorId = this.getOperatorId();\n\n // If we got this far, basic validation passed\n return {\n isValid: true,\n operator: { accountId: operatorId },\n };\n } catch (error) {\n this.logger.error(`Validation error: ${error}`);\n return {\n isValid: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n }\n\n async initializeWithValidation(options: ClientValidationOptions): Promise<{\n isValid: boolean;\n operator?: { accountId: string };\n error?: string;\n }> {\n const validationResult = await this.validateOperator(options);\n\n if (validationResult.isValid) {\n // If we have access to the state manager, initialize its connections manager\n if (options.stateManager) {\n options.stateManager.initializeConnectionsManager(this.standardClient);\n }\n }\n\n return validationResult;\n }\n}\n","import {\n AIAgentCapability,\n Logger,\n FeeConfigBuilder,\n} from '@hashgraphonline/standards-sdk';\nimport { ensureAgentHasEnoughHbar } from '../utils/ensure-agent-has-hbar';\nimport { HCS10Client, ExtendedAgentMetadata } from '../hcs10/HCS10Client';\nimport { StructuredTool } from '@langchain/core/tools';\nimport { z } from 'zod';\nimport { IStateManager } from '../state/state-types';\nimport { AgentPersistenceOptions } from '../state/state-types';\nimport fs from 'fs';\nimport path from 'path';\nimport axios from 'axios';\n\n/**\n * Interface for HCS10 registration result\n */\ninterface HCS10RegistrationResult {\n metadata?: {\n accountId?: string;\n inboundTopicId?: string;\n outboundTopicId?: string;\n profileTopicId?: string;\n privateKey?: string;\n capabilities?: number[];\n [key: string]: string | number | boolean | number[] | object | undefined;\n };\n}\n\n/**\n * Agent registration details returned when successful\n */\ninterface AgentRegistrationDetails {\n success: boolean;\n message: string;\n name: string;\n accountId: string;\n privateKey: string;\n inboundTopicId: string;\n outboundTopicId: string;\n profileTopicId: string;\n capabilities: number[];\n hasFees: boolean;\n hbarFee: number;\n tokenFee: { amount: number; tokenId: string } | null;\n profilePicture?: {\n source: string;\n topicId?: string;\n };\n}\n\n/**\n * Profile picture input types supported by the tool\n */\ntype ProfilePictureInput =\n | string\n | {\n url: string;\n filename: string;\n }\n | {\n path: string;\n filename?: string;\n };\n\n/**\n * RegisterAgentTool wraps the createAndRegisterAgent() function of HCS10Client.\n * It creates and registers an agent on Hedera using the HCS-10 standard SDK flow.\n * On success, returns a JSON string containing the new agent's details (including private key).\n */\nexport class RegisterAgentTool extends StructuredTool {\n name = 'register_agent';\n description =\n \"Creates and registers the AI agent on the Hedera network. Returns JSON string with agent details (accountId, privateKey, topics) on success. Optionally supports fee configuration for the agent's inbound topic using HBAR or specific tokens.\";\n private client: HCS10Client;\n private stateManager?: IStateManager;\n\n schema = z.object({\n name: z.string().describe('The name of the agent to register'),\n description: z\n .string()\n .optional()\n .describe('Optional description of the agent'),\n type: z\n .enum(['autonomous', 'manual'])\n .optional()\n .describe('Optional agent type (default: autonomous)'),\n model: z\n .string()\n .optional()\n .describe('Optional model identifier for the agent'),\n capabilities: z\n .array(z.number())\n .optional()\n .describe(\n 'Optional array of AIAgentCapability enum values (0-18). If not provided, defaults to just TEXT_GENERATION (0)'\n ),\n profilePicture: z\n .union([\n z.string().describe('Path to a local image file or URL to an image'),\n z.object({\n url: z.string().describe('URL to an image file'),\n filename: z.string().describe('Filename to use for the image'),\n }),\n z.object({\n path: z.string().describe('Path to a local image file'),\n filename: z.string().optional().describe('Optional custom filename'),\n }),\n ])\n .optional()\n .describe(\n 'Optional profile picture for the agent (local file path or URL)'\n ),\n feeCollectorAccountId: z\n .string()\n .optional()\n .describe(\n \"The account ID to collect fees. If not specified, the new agent's account ID will be used. Required if any fee is specified.\"\n ),\n hbarFee: z\n .number()\n .optional()\n .describe(\n 'Optional: The fee amount in HBAR to charge per message on the inbound topic (e.g., 0.5). If specified, inboundTopicType will be set to FEE_BASED.'\n ),\n tokenFee: z\n .object({\n amount: z.number(),\n tokenId: z.string(),\n })\n .optional()\n .describe(\n 'Optional: The fee amount and token ID to charge per message on the inbound topic (e.g., { amount: 10, tokenId: \"0.0.12345\" }). If specified, inboundTopicType will be set to FEE_BASED.'\n ),\n hbarFees: z\n .array(\n z.object({\n amount: z.number(),\n collectorAccount: z.string().optional(),\n })\n )\n .optional()\n .describe(\n 'Optional: Array of HBAR fees with different collectors. If specified, inboundTopicType will be set to FEE_BASED.'\n ),\n tokenFees: z\n .array(\n z.object({\n amount: z.number(),\n tokenId: z.string(),\n collectorAccount: z.string().optional(),\n })\n )\n .optional()\n .describe(\n 'Optional: Array of token fees with different collectors. If specified, inboundTopicType will be set to FEE_BASED.'\n ),\n exemptAccountIds: z\n .array(z.string())\n .optional()\n .describe(\n 'Optional: Array of account IDs to exempt from ALL fees set for this agent.'\n ),\n setAsCurrent: z\n .boolean()\n .optional()\n .describe(\n 'Optional: Whether to set the newly registered agent as the current active agent in the state manager. Default: true'\n ),\n persistence: z\n .object({\n prefix: z.string().optional(),\n })\n .optional()\n .describe(\n 'Optional: Configuration for persisting agent data to environment variables. The prefix will determine the environment variable names (e.g., PREFIX_ACCOUNT_ID). Defaults to TODD if not specified.'\n ),\n });\n\n /**\n * Creates a new RegisterAgentTool instance\n * @param client - Instance of HCS10Client (already configured with operator/network)\n * @param stateManager - Optional state manager to store agent details\n */\n constructor(client: HCS10Client, stateManager?: IStateManager) {\n super();\n this.client = client;\n this.stateManager = stateManager;\n }\n\n /**\n * Loads a profile picture from a local file or URL and returns a buffer\n * @param profilePicture - Local file path or URL\n * @returns Object containing buffer and filename\n */\n private async loadProfilePicture(\n profilePicture: ProfilePictureInput\n ): Promise<{ buffer: Buffer; filename: string } | null> {\n const logger = Logger.getInstance({\n level: 'debug',\n });\n\n try {\n if (!profilePicture) {\n return null;\n }\n\n if (typeof profilePicture === 'string') {\n const isUrl =\n profilePicture.startsWith('http://') ||\n profilePicture.startsWith('https://');\n\n if (isUrl) {\n logger.info(`Loading profile picture from URL: ${profilePicture}`);\n const response = await axios.get(profilePicture, {\n responseType: 'arraybuffer',\n });\n const buffer = Buffer.from(response.data);\n\n const urlPathname = new URL(profilePicture).pathname;\n const filename = path.basename(urlPathname) || 'profile.png';\n\n return { buffer, filename };\n } else {\n if (!fs.existsSync(profilePicture)) {\n logger.warn(`Profile picture file not found: ${profilePicture}`);\n return null;\n }\n\n logger.info(`Loading profile picture from file: ${profilePicture}`);\n const buffer = fs.readFileSync(profilePicture);\n const filename = path.basename(profilePicture);\n\n return { buffer, filename };\n }\n }\n\n if ('url' in profilePicture) {\n logger.info(`Loading profile picture from URL: ${profilePicture.url}`);\n const response = await axios.get(profilePicture.url, {\n responseType: 'arraybuffer',\n });\n const buffer = Buffer.from(response.data);\n const filename = profilePicture.filename || 'profile.png';\n\n return { buffer, filename };\n }\n\n if ('path' in profilePicture) {\n if (!fs.existsSync(profilePicture.path)) {\n logger.warn(`Profile picture file not found: ${profilePicture.path}`);\n return null;\n }\n\n logger.info(\n `Loading profile picture from file: ${profilePicture.path}`\n );\n const buffer = fs.readFileSync(profilePicture.path);\n const filename =\n profilePicture.filename || path.basename(profilePicture.path);\n\n return { buffer, filename };\n }\n\n return null;\n } catch (error) {\n logger.error('Failed to load profile picture:', error);\n return null;\n }\n }\n\n /**\n * Calls createAndRegisterAgent() with the provided metadata.\n * Returns a JSON string with agent details on success, or an error string.\n */\n async _call(input: z.infer<typeof this.schema>): Promise<string> {\n const logger = Logger.getInstance({\n level: 'debug',\n });\n\n const metadata: ExtendedAgentMetadata = {\n name: input.name,\n description: input.description,\n type: input.type,\n model: input.model,\n capabilities: input.capabilities || [AIAgentCapability.TEXT_GENERATION],\n properties: {},\n };\n\n let profilePictureSource = '';\n if (input.profilePicture) {\n const profilePictureData = await this.loadProfilePicture(\n input.profilePicture\n );\n if (profilePictureData) {\n const { buffer, filename } = profilePictureData;\n metadata.pfpBuffer = buffer;\n metadata.pfpFileName = filename;\n\n if (typeof input.profilePicture === 'string') {\n profilePictureSource = input.profilePicture;\n } else if ('url' in input.profilePicture) {\n profilePictureSource = input.profilePicture.url;\n } else if ('path' in input.profilePicture) {\n profilePictureSource = input.profilePicture.path;\n }\n }\n }\n\n const hasHbarFee = input.hbarFee !== undefined && input.hbarFee > 0;\n const hasTokenFee = this.hasValidTokenFee(input.tokenFee);\n const hasHbarFees = input.hbarFees && input.hbarFees.length > 0;\n const hasTokenFees = input.tokenFees && input.tokenFees.length > 0;\n\n if (hasHbarFee || hasTokenFee || hasHbarFees || hasTokenFees) {\n const { accountId: operatorAccountId } =\n this.client.getAccountAndSigner();\n const collectorId = input.feeCollectorAccountId || operatorAccountId;\n\n if (!collectorId) {\n return 'Error: Fee collector account ID is required when specifying fees and could not be determined.';\n }\n\n const feeConfigBuilder = new FeeConfigBuilder({\n network: this.client.getNetwork(),\n logger,\n });\n\n try {\n const exemptAccountIds =\n input.exemptAccountIds?.filter(\n (id) => id !== collectorId && id.startsWith('0.0')\n ) || [];\n\n let updatedFeeConfig = feeConfigBuilder;\n\n if (hasHbarFee) {\n logger.info(\n `Adding HBAR fee: ${input.hbarFee} HBAR to be collected by ${collectorId}`\n );\n updatedFeeConfig = updatedFeeConfig.addHbarFee(\n input.hbarFee!,\n collectorId,\n exemptAccountIds\n );\n }\n\n if (hasHbarFees) {\n for (const fee of input.hbarFees!) {\n const feeCollector = fee.collectorAccount || collectorId;\n logger.info(\n `Adding HBAR fee: ${fee.amount} HBAR to be collected by ${feeCollector}`\n );\n updatedFeeConfig = updatedFeeConfig.addHbarFee(\n fee.amount,\n feeCollector,\n exemptAccountIds\n );\n }\n }\n\n if (hasTokenFee) {\n logger.info(\n `Adding token fee: ${input.tokenFee!.amount} of token ${\n input.tokenFee!.tokenId\n } to be collected by ${collectorId}`\n );\n updatedFeeConfig = await updatedFeeConfig.addTokenFee(\n input.tokenFee!.amount,\n input.tokenFee!.tokenId,\n collectorId,\n undefined,\n exemptAccountIds\n );\n }\n\n if (hasTokenFees) {\n for (const fee of input.tokenFees!) {\n const feeCollector = fee.collectorAccount || collectorId;\n logger.info(\n `Adding token fee: ${fee.amount} of token ${fee.tokenId} to be collected by ${feeCollector}`\n );\n updatedFeeConfig = await updatedFeeConfig.addTokenFee(\n fee.amount,\n fee.tokenId,\n feeCollector,\n undefined,\n exemptAccountIds\n );\n }\n }\n\n metadata.feeConfig = updatedFeeConfig;\n logger.info('FeeConfigBuilder created successfully');\n } catch (error) {\n return `Error: Failed to configure fees. Reason: ${\n error instanceof Error ? error.message : String(error)\n }`;\n }\n }\n\n try {\n logger.info('Registering agent with metadata');\n\n const result = (await this.client.createAndRegisterAgent(\n metadata\n )) as unknown as HCS10RegistrationResult;\n\n return this.processRegistrationResult(\n result,\n input,\n profilePictureSource\n );\n } catch (error) {\n return `Error: Failed to create/register agent \"${input.name}\". Reason: ${\n error instanceof Error ? error.message : String(error)\n }`;\n }\n }\n\n /**\n * Checks if the token fee configuration is valid\n */\n private hasValidTokenFee(tokenFee?: {\n amount: number;\n tokenId: string;\n }): boolean {\n return !!(\n tokenFee &&\n tokenFee.amount > 0 &&\n tokenFee.tokenId &&\n tokenFee.tokenId.trim() !== ''\n );\n }\n\n /**\n * Processes the registration result and returns formatted output\n */\n private async processRegistrationResult(\n result: HCS10RegistrationResult,\n input: z.infer<typeof this.schema>,\n profilePictureSource: string = ''\n ): Promise<string> {\n const newAgentAccountId = result?.metadata?.accountId || '';\n const inboundTopicId = result?.metadata?.inboundTopicId || '';\n const outboundTopicId = result?.metadata?.outboundTopicId || '';\n const profileTopicId = result?.metadata?.profileTopicId || '';\n const privateKey = result?.metadata?.privateKey || '';\n const pfpTopicId = result?.metadata?.pfpTopicId;\n\n this.validateRegistrationResult(\n newAgentAccountId,\n inboundTopicId,\n outboundTopicId,\n privateKey\n );\n\n if (\n this.stateManager &&\n privateKey &&\n newAgentAccountId &&\n inboundTopicId &&\n outboundTopicId &&\n (input.setAsCurrent === undefined || input.setAsCurrent)\n ) {\n const agent = {\n name: input.name,\n accountId: newAgentAccountId,\n inboundTopicId,\n outboundTopicId,\n profileTopicId,\n privateKey,\n pfpTopicId: pfpTopicId as string,\n };\n\n this.stateManager.setCurrentAgent(agent);\n\n if (this.stateManager.persistAgentData && input.persistence) {\n try {\n const persistenceOptions: AgentPersistenceOptions = {\n type: 'env-file',\n prefix: input.persistence.prefix,\n };\n\n await this.stateManager.persistAgentData(agent, persistenceOptions);\n } catch (error) {\n Logger.getInstance().warn('Failed to persist agent data', error);\n }\n }\n }\n\n await this.ensureAgentHasFunds(newAgentAccountId, input.name);\n\n const feeDescription = this.createFeeDescription(input);\n const feeMessage = feeDescription\n ? ` with ${feeDescription} fee on inbound topic`\n : '';\n\n const registrationDetails: AgentRegistrationDetails = {\n success: true,\n message: `Successfully registered agent '${input.name}'${feeMessage}.`,\n name: input.name,\n accountId: newAgentAccountId,\n privateKey: privateKey,\n inboundTopicId: inboundTopicId,\n outboundTopicId: outboundTopicId,\n profileTopicId: profileTopicId || 'N/A',\n capabilities: input.capabilities || [AIAgentCapability.TEXT_GENERATION],\n hasFees: !!(input.hbarFee || this.hasValidTokenFee(input.tokenFee)),\n hbarFee: input.hbarFee || 0,\n tokenFee: input.tokenFee || null,\n };\n\n if (pfpTopicId || profilePictureSource) {\n registrationDetails.profilePicture = {\n source: profilePictureSource,\n topicId: pfpTopicId as string,\n };\n }\n\n return JSON.stringify(registrationDetails);\n }\n\n /**\n * Ensures the agent has enough HBAR for operations\n */\n private async ensureAgentHasFunds(\n accountId: string,\n agentName: string\n ): Promise<void> {\n try {\n await ensureAgentHasEnoughHbar(\n Logger.getInstance({\n module: 'RegisterAgentTool',\n }),\n this.client.standardClient,\n accountId,\n agentName\n );\n } catch (error) {\n Logger.getInstance().error('Failed to auto fund agent', error);\n }\n }\n\n /**\n * Validates that all required fields are present in the registration result\n */\n private validateRegistrationResult(\n accountId?: string,\n inboundTopicId?: string,\n outboundTopicId?: string,\n privateKey?: string\n ): void {\n if (!accountId || !inboundTopicId || !outboundTopicId || !privateKey) {\n const missingFields = [\n !accountId && 'accountId',\n !inboundTopicId && 'inboundTopicId',\n !outboundTopicId && 'outboundTopicId',\n !privateKey && 'privateKey',\n ]\n .filter(Boolean)\n .join(', ');\n throw new Error(\n `Registration failed. The HCS client returned incomplete details (Missing: ${missingFields}).`\n );\n }\n }\n\n /**\n * Creates a description of the fees configured for the agent\n */\n private createFeeDescription(input: z.infer<typeof this.schema>): string {\n const hasHbarFee = input.hbarFee && input.hbarFee > 0;\n const hasTokenFee = this.hasValidTokenFee(input.tokenFee);\n if (!hasHbarFee && !hasTokenFee) {\n return '';\n }\n\n let description = '';\n if (hasHbarFee) {\n description += `${input.hbarFee} HBAR`;\n }\n if (hasTokenFee && input.tokenFee) {\n const tokenFeeText = `${input.tokenFee.amount} of token ${input.tokenFee.tokenId}`;\n description += description ? ` and ${tokenFeeText}` : tokenFeeText;\n }\n return description;\n }\n}\n","import { Hbar } from \"@hashgraph/sdk\";\nimport { TransferTransaction } from \"@hashgraph/sdk\";\nimport { Logger, HCS10Client, HederaMirrorNode } from \"@hashgraphonline/standards-sdk\";\n\nexport const MIN_REQUIRED_USD = 2.0;\nexport const MIN_REQUIRED_HBAR_USD = 10.0;\n\nexport async function ensureAgentHasEnoughHbar(\n logger: Logger,\n baseClient: HCS10Client,\n accountId: string,\n agentName: string\n): Promise<void> {\n try {\n const account = await baseClient.requestAccount(accountId);\n const balance = account.balance.balance;\n const hbarBalance = balance / 100_000_000;\n\n logger.info(`${agentName} account ${accountId} has ${hbarBalance} HBAR`);\n\n try {\n const mirrorNode = new HederaMirrorNode('testnet', logger);\n const hbarPrice = await mirrorNode.getHBARPrice(new Date());\n\n if (hbarPrice) {\n const balanceInUsd = hbarBalance * hbarPrice;\n logger.info(`${agentName} balance in USD: $${balanceInUsd.toFixed(2)}`);\n\n if (balanceInUsd < MIN_REQUIRED_USD) {\n logger.warn(\n `${agentName} account ${accountId} has less than $${MIN_REQUIRED_USD} (${balanceInUsd.toFixed(\n 2\n )}). Attempting to fund.`\n );\n\n try {\n const funder = baseClient.getAccountAndSigner();\n const targetHbar = MIN_REQUIRED_HBAR_USD / hbarPrice;\n const amountToTransferHbar = Math.max(0, targetHbar - hbarBalance);\n\n if (amountToTransferHbar > 0) {\n const transferTx = new TransferTransaction()\n .addHbarTransfer(\n funder.accountId,\n Hbar.fromTinybars(\n Math.round(amountToTransferHbar * -100_000_000)\n )\n )\n .addHbarTransfer(\n accountId,\n Hbar.fromTinybars(\n Math.round(amountToTransferHbar * 100_000_000)\n )\n );\n\n logger.info(\n `Funding ${agentName} account ${accountId} with ${amountToTransferHbar.toFixed(\n 2\n )} HBAR from ${funder.accountId}`\n );\n\n const fundTxResponse = await transferTx.execute(\n baseClient.getClient() as any\n );\n await fundTxResponse.getReceipt(baseClient.getClient() as any);\n logger.info(\n `Successfully funded ${agentName} account ${accountId}.`\n );\n } else {\n logger.info(\n `${agentName} account ${accountId} does not require additional funding.`\n );\n }\n } catch (fundingError) {\n logger.error(\n `Failed to automatically fund ${agentName} account ${accountId}:`,\n fundingError\n );\n logger.warn(\n `Please fund the account ${accountId} manually with at least ${(\n MIN_REQUIRED_HBAR_USD / hbarPrice\n ).toFixed(2)} HBAR.`\n );\n }\n }\n } else {\n logger.warn(\n 'Failed to get HBAR price from Mirror Node. Please ensure the account has enough HBAR.'\n );\n }\n } catch (error) {\n logger.warn(\n 'Failed to check USD balance. Please ensure the account has enough HBAR.'\n );\n }\n } catch (error) {\n logger.error(`Failed to check ${agentName} account balance:`, error);\n }\n}","import { HCS10Client } from '../hcs10/HCS10Client';\nimport { StructuredTool } from '@langchain/core/tools';\nimport { z } from 'zod';\nimport { Logger } from '@hashgraphonline/standards-sdk';\n\n/**\n * SendMessageTool wraps the sendMessage() function of HCS10Client.\n * It sends a message to a specified Hedera topic and monitors for responses.\n */\nexport class SendMessageTool extends StructuredTool {\n name = 'send_message';\n description =\n 'Sends a message to a specified Hedera topic using HCS-10 and monitors for responses.';\n private client: HCS10Client;\n private lastProcessedTimestamp: number = 0;\n private logger: Logger;\n\n schema = z.object({\n topicId: z.string().describe('The Hedera topic ID to send the message to'),\n message: z.string().describe('The message content to send'),\n disableMonitoring: z\n .boolean()\n .optional()\n .describe('Whether to disable monitoring for responses'),\n });\n\n /**\n * @param client - Instance of HCS10Client.\n */\n constructor(client: HCS10Client) {\n super();\n this.client = client;\n this.logger = Logger.getInstance({ module: 'SendMessageTool' });\n }\n\n /**\n * Calls sendMessage() with the provided parameters.\n */\n async _call(input: {\n topicId: string;\n message: string;\n disableMonitoring: boolean;\n }): Promise<string> {\n try {\n const result = await this.client.sendMessage(\n input.topicId,\n input.message\n );\n if (!result) {\n throw new Error('Failed to send message');\n }\n this.logger.info(`Message sent with sequence number ${result}`);\n if (!input.disableMonitoring) {\n const response = await this.monitorResponses(input.topicId, result);\n return `Successfully sent message to topic ${input.topicId}${\n response ? `\\nResponse: ${response}` : ''\n }`;\n } else {\n return `Successfully sent message to topic ${input.topicId}`;\n }\n } catch (error) {\n throw new Error(\n `Failed to send message: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n private async monitorResponses(\n topicId: string,\n sequenceNumber: number\n ): Promise<string | null> {\n const maxAttempts = 10;\n let attempts = 0;\n\n while (attempts < maxAttempts) {\n try {\n const messages = await this.client.getMessageStream(topicId);\n\n for (const message of messages.messages) {\n if (\n message.created &&\n message.created.getTime() > this.lastProcessedTimestamp\n ) {\n this.lastProcessedTimestamp = message.created.getTime();\n\n const content = await this.client.getMessageContent(message.data || '');\n\n let parsedContent;\n try {\n parsedContent = JSON.parse(content);\n } catch (error) {\n this.logger.error(`Error parsing message content: ${error}`);\n continue;\n }\n if (message.sequence_number > sequenceNumber) {\n // Unwrap nested data field if present\n if (parsedContent && typeof parsedContent.data === 'string') {\n return parsedContent.data;\n }\n return JSON.stringify(parsedContent);\n }\n }\n }\n } catch (error) {\n this.logger.error(`Error monitoring responses: ${error}`);\n }\n\n attempts++;\n await new Promise((resolve) => setTimeout(resolve, 1000));\n }\n\n return null;\n }\n}\n","import { HCS10Client } from '../hcs10/HCS10Client';\nimport { StructuredTool, ToolParams } from '@langchain/core/tools';\nimport { z } from 'zod';\n// Import FeeConfigBuilder if needed for explicit fee handling\n// import { FeeConfigBuilder } from '@hashgraphonline/standards-sdk';\nimport { Logger } from '@hashgraphonline/standards-sdk';\nimport {\n IStateManager,\n ActiveConnection,\n} from '../state/state-types'; // Corrected import path/name\n\nexport interface ConnectionToolParams extends ToolParams {\n client: HCS10Client;\n stateManager: IStateManager;\n}\n\n/**\n * ConnectionTool monitors the *current* agent's inbound topic for connection requests\n * and automatically handles them using the HCS-10 standard SDK flow.\n * Use this ONLY to passively LISTEN for other agents trying to connect TO YOU.\n * This tool takes NO arguments and does NOT start outgoing connections.\n */\nexport class ConnectionTool extends StructuredTool {\n name = 'monitor_connections';\n description =\n \"Starts passively LISTENING on the current agent's own inbound topic for INCOMING HCS-10 connection requests. Handles received requests automatically. Takes NO arguments. DO NOT use this to start a new connection TO someone else.\";\n public client: HCS10Client;\n public logger: Logger;\n private stateManager: IStateManager; // Renamed property\n private isMonitoring: boolean = false; // Flag to prevent multiple monitors\n private monitoringTopic: string | null = null;\n\n // Schema now takes NO arguments\n schema = z.object({});\n\n /**\n * @param client - Instance of HCS10Client.\n * @param stateManager - Instance of StateManager for shared state management.\n */\n constructor({ client, stateManager, ...rest }: ConnectionToolParams) {\n super(rest);\n this.client = client;\n this.stateManager = stateManager; // Renamed assignment\n this.logger = Logger.getInstance({\n module: 'ConnectionTool',\n level: 'info',\n });\n }\n\n /**\n * Initiates the connection request monitoring process in the background.\n * Gets the inbound topic ID from the configured client.\n */\n async _call(/* _input: z.infer<typeof this.schema> */): Promise<string> {\n // Get inboundTopicId from the client\n let inboundTopicId: string;\n try {\n // Assuming getInboundTopicId() is implemented and available\n inboundTopicId = await this.client.getInboundTopicId();\n } catch (error) {\n const errorMsg = `Error getting inbound topic ID for monitoring: ${\n error instanceof Error ? error.message : String(error)\n }`;\n this.logger.error(errorMsg);\n return errorMsg;\n }\n\n if (!inboundTopicId) {\n return 'Error: Could not determine the inbound topic ID for the current agent.';\n }\n\n if (this.isMonitoring) {\n if (this.monitoringTopic === inboundTopicId) {\n return `Already monitoring topic ${inboundTopicId}.`;\n } else {\n return `Error: Already monitoring a different topic (${this.monitoringTopic}). Stop the current monitor first.`;\n // TODO: Add a mechanism to stop the monitor if needed.\n }\n }\n\n this.isMonitoring = true;\n this.monitoringTopic = inboundTopicId;\n this.logger.info(\n `Initiating connection request monitoring for topic ${inboundTopicId}...`\n );\n\n // Start the monitoring process asynchronously without awaiting it\n // This allows the tool call to return quickly.\n this.monitorIncomingRequests(inboundTopicId).catch((error) => {\n this.logger.error(\n `Monitoring loop for ${inboundTopicId} encountered an unrecoverable error:`,\n error\n );\n this.isMonitoring = false; // Reset flag on loop failure\n this.monitoringTopic = null;\n });\n\n return `Started monitoring inbound topic ${inboundTopicId} for connection requests in the background.`;\n }\n\n /**\n * The core monitoring loop.\n */\n private async monitorIncomingRequests(inboundTopicId: string): Promise<void> {\n this.logger.info(`Monitoring inbound topic ${inboundTopicId}...`);\n\n let lastProcessedMessageSequence = 0;\n const processedRequestIds = new Set<number>(); // Track processed requests within this monitoring session\n\n // Main monitoring loop\n while (this.isMonitoring && this.monitoringTopic === inboundTopicId) {\n try {\n const messagesResult = await this.client.getMessages(inboundTopicId);\n\n const allMessages = messagesResult.messages;\n\n const connectionRequests = allMessages.filter(\n (msg) =>\n msg.op === 'connection_request' &&\n typeof msg.sequence_number === 'number' // Keep filtering by sequence number if needed, or remove if checking existing confirmations is sufficient\n // msg.sequence_number > lastProcessedMessageSequence // Temporarily remove or adjust this if checking confirmations is the primary method\n );\n\n for (const message of connectionRequests) {\n // Update lastProcessedMessageSequence regardless of handling outcome to avoid re-checking handled/skipped messages in future loops\n lastProcessedMessageSequence = Math.max(\n lastProcessedMessageSequence,\n message.sequence_number || 0 // Use 0 if sequence_number is undefined (though filter should prevent this)\n );\n\n const connectionRequestId = message.sequence_number;\n if (!connectionRequestId) {\n continue; // Skip if sequence number is missing\n }\n\n // --- Check if already handled ---\n const alreadyHandled = allMessages.some(\n (m) => m.op === 'connection_created' && m.connection_id === connectionRequestId\n );\n\n if (alreadyHandled) {\n this.logger.debug(\n `Connection request #${connectionRequestId} already handled (found connection_created). Skipping.`\n );\n continue; // Skip to the next request\n }\n // --- End Check ---\n\n // Extract requesting account ID from the message's operator_id field (topic@account)\n const senderOperatorId = message.operator_id || '';\n const requestingAccountId = senderOperatorId.split('@')[1] || null;\n\n if (!requestingAccountId) {\n this.logger.warn(\n `Could not determine requesting account ID from operator_id '${senderOperatorId}' for request #${connectionRequestId}. Skipping.`\n );\n continue;\n }\n\n if (processedRequestIds.has(connectionRequestId)) {\n this.logger.info(\n `Connection request #${connectionRequestId} already processed in this session. Skipping.`\n );\n continue;\n }\n\n this.logger.info(\n `Processing connection request #${connectionRequestId} from account ${requestingAccountId}...`\n );\n\n try {\n // Handle the connection request using the HCS10Client wrapper\n const confirmation = await this.client.handleConnectionRequest(\n inboundTopicId,\n requestingAccountId,\n connectionRequestId\n );\n\n processedRequestIds.add(connectionRequestId);\n this.logger.info(\n `Connection confirmed for request #${connectionRequestId}. New connection topic: ${confirmation.connectionTopicId}`\n );\n\n // Use stateManager to add connection\n const newConnection: ActiveConnection = {\n targetAccountId: requestingAccountId,\n targetAgentName: `Agent ${requestingAccountId}`,\n targetInboundTopicId: 'N/A',\n connectionTopicId: confirmation.connectionTopicId,\n };\n this.stateManager.addActiveConnection(newConnection);\n this.logger.info(\n `Added new active connection to ${requestingAccountId} state.`\n );\n } catch (handleError) {\n this.logger.error(\n `Error handling connection request #${connectionRequestId} from ${requestingAccountId}:`,\n handleError\n );\n }\n }\n } catch (error) {\n this.logger.error(\n `Error fetching or processing messages for topic ${inboundTopicId}:`,\n error\n );\n // Implement backoff or error threshold if needed\n }\n\n // Wait before the next poll\n await new Promise((resolve) => setTimeout(resolve, 5000)); // Poll every 5 seconds (adjust as needed)\n }\n\n this.logger.info(`Monitoring loop stopped for topic ${inboundTopicId}.`);\n this.isMonitoring = false; // Ensure flag is reset when loop exits\n this.monitoringTopic = null;\n }\n\n // Optional: Method to explicitly stop monitoring\n public stopMonitoring(): void {\n if (this.isMonitoring) {\n this.logger.info(\n `Stopping monitoring for topic ${this.monitoringTopic}...`\n );\n this.isMonitoring = false;\n this.monitoringTopic = null;\n } else {\n this.logger.info('Monitor is not currently running.');\n }\n }\n}\n","// src/tools/send-message-to-connection-tool.ts\n\nimport { StructuredTool, ToolParams } from '@langchain/core/tools';\nimport { z } from 'zod';\nimport { HCS10Client } from '../hcs10/HCS10Client';\nimport { IStateManager } from '../state/state-types';\nimport { Logger } from '@hashgraphonline/standards-sdk'; // Assuming logger utility\n\nexport interface SendMessageToConnectionToolParams extends ToolParams {\n hcsClient: HCS10Client;\n stateManager: IStateManager;\n}\n\n/**\n * A tool to send a message to an agent over an established HCS-10 connection.\n */\nexport class SendMessageToConnectionTool extends StructuredTool {\n name = 'send_message_to_connection';\n description =\n \"Sends a text message to another agent using an existing active connection. Identify the target agent using their account ID (e.g., 0.0.12345) or the connection number shown in 'list_connections'. Return back the reply from the target agent if possible\";\n schema = z.object({\n targetIdentifier: z\n .string()\n .describe(\n \"The account ID (e.g., 0.0.12345) of the target agent OR the connection number (e.g., '1', '2') from the 'list_connections' tool.\"\n ),\n message: z.string().describe('The text message content to send.'),\n disableMonitoring: z.boolean().optional().default(false),\n });\n\n private hcsClient: HCS10Client;\n private stateManager: IStateManager;\n private logger: Logger;\n\n constructor({\n hcsClient,\n stateManager,\n ...rest\n }: SendMessageToConnectionToolParams) {\n super(rest);\n this.hcsClient = hcsClient;\n this.stateManager = stateManager;\n this.logger = Logger.getInstance({ module: 'SendMessageToConnectionTool' });\n }\n\n protected async _call({\n targetIdentifier,\n message,\n disableMonitoring,\n }: z.infer<this['schema']>): Promise<string> {\n const currentAgent = this.stateManager.getCurrentAgent();\n if (!currentAgent) {\n return 'Error: Cannot send message. No agent is currently active. Please register or select an agent first.';\n }\n\n const connection =\n this.stateManager.getConnectionByIdentifier(targetIdentifier);\n if (!connection) {\n return `Error: Could not find an active connection matching identifier \"${targetIdentifier}\". Use 'list_connections' to see active connections.`;\n }\n\n const connectionTopicId = connection.connectionTopicId;\n const targetAgentName = connection.targetAgentName;\n\n // Construct the sender's operator ID\n const operatorId = `${currentAgent.inboundTopicId}@${currentAgent.accountId}`;\n\n this.logger.info(\n `Sending message from ${operatorId} to ${targetAgentName} (${connection.targetAccountId}) via connection topic ${connectionTopicId}`\n );\n\n try {\n // Call sendMessage with correct arguments\n const sequenceNumber = await this.hcsClient.sendMessage(\n connectionTopicId,\n message, // Message content as 'data'\n `Agent message from ${currentAgent.name}` // Optional memo\n );\n\n if (!sequenceNumber) {\n throw new Error('Failed to send message');\n }\n\n if (!disableMonitoring) {\n return `Message sent to ${targetAgentName} (${connection.targetAccountId}) via connection ${connectionTopicId}. Sequence Number: ${sequenceNumber}`;\n }\n\n const replyBack = await this.monitorResponses(\n connectionTopicId,\n operatorId,\n sequenceNumber\n );\n\n if (replyBack) {\n this.logger.info(`Got reply from ${targetAgentName}`, replyBack);\n // Format the return string clearly as an observation/reply\n return `Received reply from ${targetAgentName}: ${replyBack}`;\n }\n\n // Return message based on the status string if no reply was received/awaited\n return `Message sent to ${targetAgentName} (${connection.targetAccountId}) via connection ${connectionTopicId}. Sequence Number: ${sequenceNumber}`;\n } catch (error) {\n this.logger.error(\n `Failed to send message via connection ${connectionTopicId}: ${error}`\n );\n return `Error sending message to ${targetAgentName}: ${\n error instanceof Error ? error.message : String(error)\n }`;\n }\n }\n\n private async monitorResponses(\n topicId: string,\n operatorId: string,\n sequenceNumber: number\n ): Promise<string | null> {\n const maxAttempts = 30;\n const attempts = 0;\n\n while (attempts < maxAttempts) {\n try {\n const messages = await this.hcsClient.getMessageStream(topicId);\n\n for (const message of messages.messages) {\n if (\n message.sequence_number < sequenceNumber ||\n message.operator_id === operatorId\n ) {\n continue;\n }\n const content = await this.hcsClient.getMessageContent(message.data || '');\n\n return content;\n }\n } catch (error) {\n this.logger.error(`Error monitoring responses: ${error}`);\n }\n await new Promise((resolve) => setTimeout(resolve, 4000));\n }\n return null;\n }\n}\n","import { StructuredTool, ToolParams } from '@langchain/core/tools';\nimport { z } from 'zod';\nimport { HCS10Client } from '../hcs10/HCS10Client';\nimport { IStateManager, ActiveConnection } from '../state/state-types';\nimport { Logger } from '@hashgraphonline/standards-sdk';\n\nexport interface InitiateConnectionToolParams extends ToolParams {\n hcsClient: HCS10Client;\n stateManager: IStateManager;\n}\n\n/**\n * A tool to actively START a NEW HCS-10 connection TO a target agent.\n * Requires the target agent's account ID.\n * It retrieves their profile, sends a connection request, waits for confirmation, and stores the connection using the provided stateManager.\n * Use this tool ONLY to actively INITIATE an OUTGOING connection.\n */\nexport class InitiateConnectionTool extends StructuredTool {\n name = 'initiate_connection';\n description =\n 'Actively STARTS a NEW HCS-10 connection TO a specific target agent identified by their account ID. Requires the targetAccountId parameter. Use this ONLY to INITIATE an OUTGOING connection request.';\n schema = z.object({\n targetAccountId: z\n .string()\n .describe(\n 'The Hedera account ID (e.g., 0.0.12345) of the agent you want to connect with.'\n )\n });\n\n private hcsClient: HCS10Client;\n private stateManager: IStateManager;\n private logger: Logger;\n\n constructor({\n hcsClient,\n stateManager,\n ...rest\n }: InitiateConnectionToolParams) {\n super(rest);\n this.hcsClient = hcsClient;\n this.stateManager = stateManager;\n this.logger = Logger.getInstance({ module: 'InitiateConnectionTool' });\n }\n\n protected async _call({\n targetAccountId\n }: z.infer<this['schema']>): Promise<string> {\n const currentAgent = this.stateManager.getCurrentAgent();\n if (!currentAgent) {\n return 'Error: Cannot initiate connection. No agent is currently active. Please register or select an agent first.';\n }\n\n this.logger.info(\n `Attempting connection from ${currentAgent.accountId} to ${targetAccountId}`\n );\n\n try {\n this.logger.debug(`Retrieving profile for ${targetAccountId}...`);\n const targetProfile = await this.hcsClient.getAgentProfile(\n targetAccountId\n );\n if (!targetProfile?.topicInfo?.inboundTopic) {\n return `Error: Could not retrieve profile or find inbound topic ID for target agent ${targetAccountId}. They might not be registered or have a public profile.`;\n }\n const targetInboundTopicId = targetProfile.topicInfo.inboundTopic;\n const targetAgentName =\n targetProfile.profile.name || `Agent ${targetAccountId}`;\n\n const requestResult = await this.hcsClient.submitConnectionRequest(\n targetInboundTopicId,\n currentAgent.name\n );\n const sequenceNumberLong = requestResult?.topicSequenceNumber;\n if (!sequenceNumberLong) {\n throw new Error('Connection request sequence number not found.');\n }\n\n let connectionRequestId: number;\n try {\n connectionRequestId = sequenceNumberLong.toNumber();\n if (isNaN(connectionRequestId)) {\n throw new Error('Converted sequence number is NaN.');\n }\n } catch (conversionError) {\n throw new Error(\n `Failed to convert connection request sequence number: ${conversionError}`\n );\n }\n\n const confirmationTimeoutMs = 60000;\n const delayMs = 2000;\n const maxAttempts = Math.ceil(confirmationTimeoutMs / delayMs);\n\n const confirmationResult =\n await this.hcsClient.waitForConnectionConfirmation(\n targetInboundTopicId,\n connectionRequestId,\n maxAttempts,\n delayMs\n );\n\n if (!confirmationResult?.connectionTopicId) {\n return `Error: Connection confirmation not received from ${targetAccountId} (for request ${connectionRequestId}) within ${\n confirmationTimeoutMs / 1000\n } seconds.`;\n }\n\n const connectionTopicId = confirmationResult.connectionTopicId;\n this.logger.info(`Connection confirmed! Topic ID: ${connectionTopicId}`);\n\n const newConnection: ActiveConnection = {\n targetAccountId: targetAccountId,\n targetAgentName: targetAgentName,\n targetInboundTopicId: targetInboundTopicId,\n connectionTopicId: connectionTopicId,\n };\n this.stateManager.addActiveConnection(newConnection);\n\n const connections = this.stateManager.listConnections();\n const addedEntry = connections.find(\n (c) => c.connectionTopicId === connectionTopicId\n );\n const localConnectionId = addedEntry\n ? connections.indexOf(addedEntry) + 1\n : null;\n\n const idString = localConnectionId ? `#${localConnectionId}` : '';\n\n return `Successfully established connection ${idString} with ${targetAgentName} (${targetAccountId}). Connection Topic: ${connectionTopicId}. You can now send messages using this connection.`;\n } catch (error) {\n this.logger.error(`Connection initiation failed: ${error}`);\n return `Error initiating connection with ${targetAccountId}: ${\n error instanceof Error ? error.message : String(error)\n }`;\n }\n }\n}\n","import { StructuredTool, ToolParams } from '@langchain/core/tools';\nimport { z } from 'zod';\nimport { IStateManager, ActiveConnection } from '../state/state-types';\nimport { HCS10Client } from '../hcs10/HCS10Client';\nimport { Connection, Logger } from '@hashgraphonline/standards-sdk';\n\nexport interface ListConnectionsToolParams extends ToolParams {\n stateManager: IStateManager;\n hcsClient?: HCS10Client;\n}\n\n/**\n * A tool to list currently active HCS-10 connections stored in the state manager.\n * Enhanced to show more details similar to moonscape's implementation.\n */\nexport class ListConnectionsTool extends StructuredTool {\n name = 'list_connections';\n description =\n 'Lists the currently active HCS-10 connections with detailed information. Shows connection status, agent details, and recent activity. Use this to get a comprehensive view of all active connections.';\n schema = z.object({\n includeDetails: z\n .boolean()\n .optional()\n .describe(\n 'Whether to include detailed information about each connection'\n ),\n showPending: z\n .boolean()\n .optional()\n .describe('Whether to include pending connection requests'),\n });\n\n private stateManager: IStateManager;\n private hcsClient?: HCS10Client;\n private logger: Logger;\n\n constructor({ stateManager, hcsClient, ...rest }: ListConnectionsToolParams) {\n super(rest);\n this.stateManager = stateManager;\n this.hcsClient = hcsClient;\n this.logger = new Logger({ module: 'ListConnectionsTool' });\n }\n\n protected async _call(args: z.infer<this['schema']>): Promise<string> {\n const includeDetails = args.includeDetails ?? true;\n const showPending = args.showPending ?? true;\n\n const connections = await this.getEnhancedConnections();\n\n if (connections.length === 0) {\n return 'There are currently no active connections.';\n }\n\n const activeConnections = connections.filter(\n (c) => c.status === 'established'\n );\n\n const pendingConnections = connections.filter((c) => c.isPending);\n\n const needsConfirmation = connections.filter((c) => c.needsConfirmation);\n\n let output = '';\n\n if (activeConnections.length > 0) {\n output += `🟢 Active Connections (${activeConnections.length}):\\n`;\n activeConnections.forEach((conn, index) => {\n output += this.formatConnection(conn, index, includeDetails);\n });\n output += '\\n';\n }\n\n if (showPending && needsConfirmation.length > 0) {\n output += `🟠 Connections Needing Confirmation (${needsConfirmation.length}):\\n`;\n needsConfirmation.forEach((conn, index) => {\n output += this.formatConnection(conn, index, includeDetails);\n });\n output += '\\n';\n }\n\n if (showPending && pendingConnections.length > 0) {\n output += `⚪ Pending Connection Requests (${pendingConnections.length}):\\n`;\n pendingConnections.forEach((conn, index) => {\n output += this.formatConnection(conn, index, includeDetails);\n });\n }\n\n return output.trim();\n }\n\n private formatConnection(\n conn: Connection,\n index: number,\n includeDetails: boolean\n ): string {\n let output = `${index + 1}. ${\n conn.profileInfo?.display_name || conn.targetAgentName || 'Unknown Agent'\n } (${conn.targetAccountId})\\n`;\n const displayTopicId = conn.isPending\n ? '(Pending Request)'\n : conn.connectionTopicId;\n output += ` Topic: ${displayTopicId}\\n`;\n const statusText = conn.status || 'unknown';\n output += ` Status: ${statusText}\\n`;\n\n if (includeDetails) {\n if (conn.profileInfo?.bio) {\n output += ` Bio: ${conn.profileInfo.bio.substring(0, 100)}${\n conn.profileInfo.bio.length > 100 ? '...' : ''\n }\\n`;\n }\n\n if (conn.created) {\n const createdLabel = conn.isPending\n ? 'Request sent'\n : 'Connection established';\n output += ` ${createdLabel}: ${conn.created.toLocaleString()}\\n`;\n }\n\n if (conn.lastActivity) {\n output += ` Last activity: ${conn.lastActivity.toLocaleString()}\\n`;\n }\n }\n\n return output;\n }\n\n private async getEnhancedConnections(): Promise<Connection[]> {\n if (!this.hcsClient) {\n return this.stateManager.listConnections() as Connection[];\n }\n\n try {\n const { accountId } = this.hcsClient.getAccountAndSigner();\n if (!accountId) {\n return this.stateManager.listConnections() as Connection[];\n }\n\n const connectionManager = this.stateManager.getConnectionsManager();\n if (!connectionManager) {\n this.logger.error('ConnectionsManager not initialized');\n return this.stateManager.listConnections() as Connection[];\n }\n\n const connections = await connectionManager.fetchConnectionData(\n accountId\n );\n\n for (const connection of connections) {\n this.stateManager.updateOrAddConnection(connection as ActiveConnection);\n }\n\n return connections;\n } catch (error) {\n console.error('Error fetching connection data:', error);\n return this.stateManager.listConnections() as Connection[];\n }\n }\n}\n","import { StructuredTool, ToolParams } from '@langchain/core/tools';\nimport { z } from 'zod';\nimport { HCS10Client, HCSMessageWithTimestamp } from '../hcs10/HCS10Client';\nimport { IStateManager } from '../state/state-types';\nimport { Logger } from '@hashgraphonline/standards-sdk'; // Assuming logger utility\n\nexport interface CheckMessagesToolParams extends ToolParams {\n hcsClient: HCS10Client;\n stateManager: IStateManager;\n}\n\n/**\n * A tool to check for new messages on an active HCS-10 connection topic,\n * or optionally fetch the latest messages regardless of timestamp.\n */\nexport class CheckMessagesTool extends StructuredTool {\n name = 'check_messages';\n description = `Checks for and retrieves messages from an active connection. \nIdentify the target agent using their account ID (e.g., 0.0.12345) or the connection number shown in 'list_connections'. \nBy default, it only retrieves messages newer than the last check. \nUse 'fetchLatest: true' to get the most recent messages regardless of when they arrived. \nUse 'lastMessagesCount' to specify how many latest messages to retrieve (default 1 when fetchLatest is true).`;\n schema = z.object({\n targetIdentifier: z\n .string()\n .describe(\n \"The account ID (e.g., 0.0.12345) of the target agent OR the connection number (e.g., '1', '2') from the 'list_connections' tool to check messages for.\"\n ),\n fetchLatest: z\n .boolean()\n .optional()\n .default(false)\n .describe(\n 'Set to true to fetch the latest messages even if they have been seen before, ignoring the last checked timestamp. Defaults to false (fetching only new messages).'\n ),\n lastMessagesCount: z\n .number()\n .int()\n .positive()\n .optional()\n .describe(\n 'When fetchLatest is true, specifies how many of the most recent messages to retrieve. Defaults to 1.'\n ),\n });\n\n public hcsClient: HCS10Client;\n private stateManager: IStateManager;\n private logger: Logger;\n\n constructor({ hcsClient, stateManager, ...rest }: CheckMessagesToolParams) {\n super(rest);\n this.hcsClient = hcsClient;\n this.stateManager = stateManager;\n this.logger = Logger.getInstance({ module: 'CheckMessagesTool' });\n }\n\n protected async _call({\n targetIdentifier,\n fetchLatest,\n lastMessagesCount,\n }: z.infer<this['schema']>): Promise<string> {\n const connection =\n this.stateManager.getConnectionByIdentifier(targetIdentifier);\n\n if (!connection) {\n return `Error: Could not find an active connection matching identifier \"${targetIdentifier}\". Use 'list_connections' to see active connections.`;\n }\n\n const connectionTopicId = connection.connectionTopicId;\n const targetAgentName = connection.targetAgentName;\n const lastProcessedTimestamp =\n this.stateManager.getLastTimestamp(connectionTopicId);\n\n this.logger.info(\n `Checking messages for connection with ${targetAgentName} (${connection.targetAccountId}) on topic ${connectionTopicId} (fetchLatest: ${fetchLatest}, lastCount: ${lastMessagesCount}, since: ${lastProcessedTimestamp})`\n );\n\n try {\n // 1. Get messages from the topic\n const result = await this.hcsClient.getMessages(connectionTopicId);\n const allMessages = result.messages;\n\n if (!allMessages || allMessages.length === 0) {\n return `No messages found on connection topic ${connectionTopicId}.`;\n }\n\n let messagesToProcess: HCSMessageWithTimestamp[] = [];\n let latestTimestampNanos = lastProcessedTimestamp;\n const isFetchingLatest = fetchLatest === true;\n\n if (isFetchingLatest) {\n this.logger.info('Fetching latest messages regardless of timestamp.');\n const count = lastMessagesCount ?? 1;\n messagesToProcess = allMessages.slice(-count);\n } else {\n this.logger.info(\n `Filtering for messages newer than ${lastProcessedTimestamp}`\n );\n messagesToProcess = allMessages.filter((msg) => {\n const msgTimestampNanos = msg.timestamp * 1_000_000;\n return msgTimestampNanos > lastProcessedTimestamp;\n });\n\n if (messagesToProcess.length > 0) {\n latestTimestampNanos = messagesToProcess.reduce(\n (maxTs, msg) => Math.max(maxTs, msg.timestamp * 1_000_000),\n lastProcessedTimestamp\n );\n }\n }\n\n if (messagesToProcess.length === 0) {\n return isFetchingLatest\n ? `Could not retrieve the latest message(s). No messages found on topic ${connectionTopicId}.`\n : `No new messages found for connection with ${targetAgentName} since last check.`;\n }\n\n this.logger.info(`Processing ${messagesToProcess.length} message(s).`);\n\n // 3. Process messages (resolve inscriptions, format)\n let outputString = isFetchingLatest\n ? `Latest message(s) from ${targetAgentName}:\n`\n : `New messages from ${targetAgentName}:\n`;\n\n for (const msg of messagesToProcess) {\n let content = msg.data;\n try {\n // Check for inscription HRL\n if (typeof content === 'string' && content.startsWith('hcs://')) {\n this.logger.debug(`Resolving inscribed message: ${content}`);\n content = await this.hcsClient.getMessageContent(content);\n this.logger.debug(`Resolved content length: ${content?.length}`);\n }\n\n // Attempt to parse the content as the HCS-10 structure\n let displayContent = content; // Default to raw content\n try {\n const parsed = JSON.parse(content || '{}');\n if (\n parsed.p === 'hcs-10' &&\n parsed.op === 'message' &&\n parsed.data\n ) {\n // Extract sender and actual data from standard message format\n const senderOpId = parsed.operator_id || 'unknown_sender';\n displayContent = `[${senderOpId}]: ${parsed.data}`;\n } else {\n // If not standard format, maybe just show raw stringified version\n displayContent = content; // Keep raw if parsing worked but not expected format\n }\n } catch (parseError) {\n // Content wasn't JSON, keep raw content\n displayContent = content;\n }\n\n const messageDate = new Date(msg.timestamp);\n outputString += `\\n[${messageDate.toLocaleString()}] (Seq: ${\n msg.sequence_number\n })\n${displayContent}\n`;\n } catch (error) {\n const errorMsg = `Error processing message (Seq: ${\n msg.sequence_number\n }): ${error instanceof Error ? error.message : String(error)}`;\n this.logger.error(errorMsg);\n outputString += `\\n[Error processing message Seq: ${msg.sequence_number}]\\n`;\n }\n }\n\n // 4. Update the timestamp in demo state ONLY if fetching NEW messages\n if (!isFetchingLatest && latestTimestampNanos > lastProcessedTimestamp) {\n this.logger.debug(\n `Updating timestamp for topic ${connectionTopicId} to ${latestTimestampNanos}`\n );\n this.stateManager.updateTimestamp(\n connectionTopicId,\n latestTimestampNanos\n );\n }\n\n return outputString.trim();\n } catch (error) {\n this.logger.error(\n `Failed to check messages for topic ${connectionTopicId}: ${error}`\n );\n return `Error checking messages for ${targetAgentName}: ${\n error instanceof Error ? error.message : String(error)\n }`;\n }\n }\n}\n","import { StructuredTool, ToolParams } from '@langchain/core/tools';\nimport { z } from 'zod';\nimport { HCS10Client } from '../hcs10/HCS10Client';\nimport {\n AIAgentCapability,\n Logger,\n RegistrationSearchOptions,\n} from '@hashgraphonline/standards-sdk';\n\nexport interface FindRegistrationsToolParams extends ToolParams {\n hcsClient: HCS10Client;\n}\n\n/**\n * A tool to search for registered HCS-10 agents using the configured registry.\n */\nexport class FindRegistrationsTool extends StructuredTool {\n name = 'find_registrations';\n description =\n 'Searches the configured agent registry for HCS-10 agents. You can filter by account ID or tags. Returns basic registration info.';\n schema = z.object({\n accountId: z\n .string()\n .optional()\n .describe(\n 'Optional: Filter registrations by a specific Hedera account ID (e.g., 0.0.12345).'\n ),\n tags: z\n .array(z.nativeEnum(AIAgentCapability))\n .optional()\n .describe(\n 'Optional: Filter registrations by a list of tags (API filter only).'\n ),\n });\n\n private hcsClient: HCS10Client;\n private logger: Logger;\n\n constructor({ hcsClient, ...rest }: FindRegistrationsToolParams) {\n super(rest);\n this.hcsClient = hcsClient;\n this.logger = Logger.getInstance({ module: 'FindRegistrationsTool' });\n }\n\n protected async _call({\n accountId,\n tags,\n }: z.infer<this['schema']>): Promise<string> {\n this.logger.info(\n 'Searching registrations with filters - Account ID',\n JSON.stringify({\n accountId,\n tags,\n })\n );\n\n const options: RegistrationSearchOptions = {};\n if (accountId) {\n options.accountId = accountId;\n }\n if (tags && tags.length > 0) {\n options.tags = tags;\n }\n options.network = this.hcsClient.getNetwork();\n\n try {\n if (!this.hcsClient.standardClient) {\n throw new Error(\n 'Standard SDK client instance is not available in HCS10Client wrapper.'\n );\n }\n const result = await this.hcsClient.standardClient.findRegistrations(\n options\n );\n\n if (!result.success || result.error) {\n return `Error finding registrations: ${\n result.error || 'Unknown error'\n }`;\n }\n\n if (!result.registrations || result.registrations.length === 0) {\n return 'No registrations found matching the criteria.';\n }\n\n // Format the results based on available data from RegistrationSearchResult\n let output = `Found ${result.registrations.length} registration(s):\\n`;\n result.registrations.forEach((reg, index: number) => {\n const metadata = reg.metadata;\n output += `${index + 1}. Name: ${metadata.alias || 'N/A'}\\n`;\n output += `Description: ${metadata.bio || 'N/A'}\\n`;\n output += ` Account ID: ${reg.accountId}\\n`;\n output += ` Status: ${reg.status}\\n`;\n output += ` Model: ${metadata.properties?.model || 'N/A'}\\n`;\n if (metadata.properties?.capabilities && metadata.properties.capabilities.length > 0) {\n output += ` Capabilities: ${metadata.properties.capabilities.join(', ')}\\n`;\n }\n if (metadata.properties) {\n output += ` Properties: ${JSON.stringify(metadata.properties)}\\n`;\n }\n output += ` Inbound Topic: ${reg.inboundTopicId}\\n`;\n output += ` Outbound Topic: ${reg.outboundTopicId}\\n`;\n output += ` Created At: ${reg.createdAt}\\n`;\n });\n\n return output.trim();\n } catch (error) {\n this.logger.error(`Failed to execute findRegistrations: ${error}`);\n return `Error searching registrations: ${\n error instanceof Error ? error.message : String(error)\n }`;\n }\n }\n}\n","import { StructuredTool, ToolParams } from '@langchain/core/tools';\nimport { z } from 'zod';\nimport { HCS10Client } from '../hcs10/HCS10Client';\nimport {\n IStateManager,\n ActiveConnection,\n AgentProfileInfo,\n} from '../state/state-types';\nimport {\n Logger,\n FeeConfigBuilder,\n HCSMessage,\n FeeConfigBuilderInterface,\n AIAgentProfile,\n} from '@hashgraphonline/standards-sdk';\nimport { ListConnectionsTool } from './ListConnectionsTool';\n\nexport interface FeeDefinition {\n amount: number;\n collectorAccount?: string;\n}\n\nexport interface TokenFeeDefinition extends FeeDefinition {\n tokenId: string;\n}\n\nexport interface ConnectionMonitorToolParams extends ToolParams {\n hcsClient: HCS10Client;\n stateManager: IStateManager;\n}\n\n/**\n * A tool for monitoring incoming connection requests and accepting them with optional fee settings.\n */\nexport class ConnectionMonitorTool extends StructuredTool {\n name = 'monitor_connections';\n description =\n 'Monitors for incoming connection requests and accepts them with optional fee settings. Use this to watch for connection requests and accept them, optionally setting HBAR or token fees on the connection.';\n schema = z.object({\n acceptAll: z\n .boolean()\n .optional()\n .describe(\n 'Whether to automatically accept all incoming connection requests. Default is false.'\n ),\n targetAccountId: z\n .string()\n .optional()\n .describe(\n 'If provided, only accept connection requests from this specific account ID.'\n ),\n hbarFees: z\n .array(\n z.object({\n amount: z.number(),\n collectorAccount: z.string().optional(),\n })\n )\n .optional()\n .describe(\n 'Array of HBAR fee amounts to charge per message (with optional collector accounts).'\n ),\n tokenFees: z\n .array(\n z.object({\n amount: z.number(),\n tokenId: z.string(),\n collectorAccount: z.string().optional(),\n })\n )\n .optional()\n .describe(\n 'Array of token fee amounts and IDs to charge per message (with optional collector accounts).'\n ),\n exemptAccountIds: z\n .array(z.string())\n .optional()\n .describe(\n 'Array of account IDs to exempt from ALL fees set in this request.'\n ),\n monitorDurationSeconds: z\n .number()\n .optional()\n .describe(\n 'How long to monitor for incoming requests in seconds. Default is 60.'\n ),\n defaultCollectorAccount: z\n .string()\n .optional()\n .describe(\n 'Default account to collect fees if not specified at the fee level. Defaults to the agent account.'\n ),\n });\n\n private hcsClient: HCS10Client;\n private stateManager: IStateManager;\n private logger: Logger;\n private isMonitoring: boolean = false;\n private listConnectionsTool: ListConnectionsTool;\n\n constructor({\n hcsClient,\n stateManager,\n ...rest\n }: ConnectionMonitorToolParams) {\n super(rest);\n this.hcsClient = hcsClient;\n this.stateManager = stateManager;\n this.logger = Logger.getInstance({\n module: 'ConnectionMonitorTool',\n level: 'error',\n });\n this.listConnectionsTool = new ListConnectionsTool({\n stateManager,\n hcsClient,\n ...rest,\n });\n }\n\n updateClient(newClient: HCS10Client): void {\n this.hcsClient = newClient;\n this.logger.info('Updated HCS10Client instance for ConnectionMonitorTool');\n this.listConnectionsTool = new ListConnectionsTool({\n stateManager: this.stateManager,\n hcsClient: newClient,\n });\n }\n\n protected async _call({\n acceptAll = false,\n targetAccountId,\n hbarFees = [],\n tokenFees = [],\n exemptAccountIds,\n monitorDurationSeconds = 60,\n defaultCollectorAccount,\n }: z.infer<this['schema']>): Promise<string> {\n const currentAgent = this.stateManager.getCurrentAgent();\n if (!currentAgent) {\n return 'Error: Cannot monitor for connections. No agent is currently active. Please register or select an agent first.';\n }\n\n if (this.isMonitoring) {\n return 'Already monitoring for connection requests. Please wait for the current monitoring session to complete.';\n }\n\n try {\n this.isMonitoring = true;\n const inboundTopicId = await this.hcsClient.getInboundTopicId();\n\n if (!inboundTopicId) {\n this.isMonitoring = false;\n return 'Error: Could not find inbound topic ID for the current agent.';\n }\n\n this.logger.info(\n `Starting to monitor inbound topic ${inboundTopicId} for connection requests...`\n );\n\n const feeConfig = this.createFeeConfig(\n hbarFees,\n tokenFees,\n exemptAccountIds,\n targetAccountId,\n defaultCollectorAccount\n );\n\n const endTime = Date.now() + monitorDurationSeconds * 1000;\n const pollIntervalMs = 3000;\n let lastSequenceNumber = 0;\n let connectionRequestsFound = 0;\n let acceptedConnections = 0;\n let skippedRequests = 0;\n\n while (Date.now() < endTime) {\n try {\n await this.listConnectionsTool.invoke({\n includeDetails: false,\n showPending: false,\n });\n const currentConnections = this.stateManager.listConnections();\n\n // Create a map of connections by accountId and requestId to better track multiple connections\n const connectionsByAccountAndRequest = new Map<string, Set<string>>();\n\n currentConnections\n .filter((conn) => conn.status === 'established' && !conn.isPending)\n .forEach((conn) => {\n if (!connectionsByAccountAndRequest.has(conn.targetAccountId)) {\n connectionsByAccountAndRequest.set(\n conn.targetAccountId,\n new Set()\n );\n }\n\n if (conn.connectionRequestId) {\n connectionsByAccountAndRequest\n .get(conn.targetAccountId)\n ?.add(String(conn.connectionRequestId));\n }\n });\n\n const messagesResult = await this.hcsClient.getMessages(\n inboundTopicId\n );\n const newMessages = messagesResult.messages.filter((msg) => {\n if (\n !msg.sequence_number ||\n msg.sequence_number <= lastSequenceNumber\n ) {\n return false;\n }\n lastSequenceNumber = Math.max(\n lastSequenceNumber,\n msg.sequence_number\n );\n return msg.op === 'connection_request';\n });\n\n for (const request of newMessages) {\n const requestId = request.sequence_number;\n if (!requestId) {\n continue;\n }\n\n connectionRequestsFound++;\n\n // Get the inbound topic ID where this request was received\n const inboundTopicId =\n (await this.hcsClient.getInboundTopicId()) || '';\n\n // Get ConnectionsManager from state manager\n const connectionsManager =\n this.stateManager.getConnectionsManager();\n if (!connectionsManager) {\n this.logger.error(\n 'ConnectionsManager not initialized in state manager'\n );\n continue;\n }\n\n // Check if we've already processed this specific request\n if (\n connectionsManager.isConnectionRequestProcessed(\n inboundTopicId,\n requestId\n )\n ) {\n this.logger.info(\n `Request #${requestId} already processed, skipping`\n );\n skippedRequests++;\n continue;\n }\n\n const requestorAccountId = this.extractAccountId(request);\n if (!requestorAccountId) {\n // Mark as processed even if we couldn't extract the account ID\n connectionsManager.markConnectionRequestProcessed(\n inboundTopicId,\n requestId\n );\n continue;\n }\n\n if (targetAccountId && requestorAccountId !== targetAccountId) {\n this.logger.info(\n `Request #${requestId} doesn't match target ${targetAccountId}`\n );\n continue;\n }\n\n // Check if this specific request has already been processed\n const existingAccountConnections =\n connectionsByAccountAndRequest.get(requestorAccountId);\n if (existingAccountConnections?.has(String(requestId))) {\n this.logger.info(\n `Already processed connection request #${requestId} from ${requestorAccountId}, skipping`\n );\n connectionsManager.markConnectionRequestProcessed(\n inboundTopicId,\n requestId\n );\n skippedRequests++;\n continue;\n }\n\n if (acceptAll) {\n const result = await this.acceptConnectionRequest(\n requestId,\n requestorAccountId,\n feeConfig\n );\n connectionsManager.markConnectionRequestProcessed(\n inboundTopicId,\n requestId\n );\n\n if (result.success) {\n acceptedConnections++;\n this.logger.info(\n `Successfully accepted connection with ${requestorAccountId} for request #${requestId}`\n );\n }\n } else {\n this.logger.info(\n `Found request #${requestId} from ${requestorAccountId} (not auto-accepting)`\n );\n }\n }\n\n await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));\n } catch (error) {\n this.logger.error(`Error polling for messages: ${error}`);\n await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));\n }\n }\n\n this.isMonitoring = false;\n\n if (connectionRequestsFound === 0) {\n return `No connection requests received during the ${monitorDurationSeconds} second monitoring period.`;\n } else if (acceptAll) {\n return `Monitored for ${monitorDurationSeconds} seconds. Found ${connectionRequestsFound} connection requests, accepted ${acceptedConnections} connections, skipped ${skippedRequests} existing connections${this.formatFeeString(\n hbarFees,\n tokenFees\n )}.`;\n } else {\n return `Monitored for ${monitorDurationSeconds} seconds. Found ${connectionRequestsFound} connection requests. To accept them, call this tool again with acceptAll=true.`;\n }\n } catch (error) {\n this.isMonitoring = false;\n this.logger.error(`Connection monitoring failed: ${error}`);\n return `Error monitoring for connections: ${\n error instanceof Error ? error.message : String(error)\n }`;\n }\n }\n\n private createFeeConfig(\n hbarFees: FeeDefinition[] = [],\n tokenFees: TokenFeeDefinition[] = [],\n exemptAccountIds?: string[],\n targetAccountId?: string,\n defaultCollectorAccount?: string\n ): FeeConfigBuilderInterface | undefined {\n if (hbarFees.length === 0 && tokenFees.length === 0) {\n return undefined;\n }\n\n try {\n const agentAccountId = this.hcsClient.getAccountAndSigner().accountId;\n const defaultCollector = defaultCollectorAccount || agentAccountId;\n\n const builder = new FeeConfigBuilder({\n network: this.hcsClient.getNetwork(),\n logger: this.logger,\n defaultCollectorAccountId: defaultCollector,\n });\n\n const exemptIds = [...(exemptAccountIds || [])];\n if (targetAccountId && !exemptIds.includes(targetAccountId)) {\n exemptIds.push(targetAccountId);\n }\n\n for (const hbarFee of hbarFees) {\n if (hbarFee.amount > 0) {\n const collector = hbarFee.collectorAccount || defaultCollector;\n builder.addHbarFee(hbarFee.amount, collector, exemptIds);\n this.logger.info(\n `Added HBAR fee: ${hbarFee.amount} HBAR to be collected by ${collector}`\n );\n }\n }\n\n for (const tokenFee of tokenFees) {\n if (tokenFee.amount > 0 && tokenFee.tokenId) {\n const collector = tokenFee.collectorAccount || defaultCollector;\n builder.addTokenFee(\n tokenFee.amount,\n tokenFee.tokenId,\n collector,\n undefined,\n exemptIds\n );\n this.logger.info(\n `Added token fee: ${tokenFee.amount} of token ${tokenFee.tokenId} to be collected by ${collector}`\n );\n }\n }\n\n return builder;\n } catch (error) {\n this.logger.error(`Error creating fee configuration: ${error}`);\n return undefined;\n }\n }\n\n private extractAccountId(request: HCSMessage): string | undefined {\n if (request.operator_id) {\n return this.hcsClient.standardClient.extractAccountFromOperatorId(\n request.operator_id\n );\n }\n return undefined;\n }\n\n private async acceptConnectionRequest(\n connectionRequestId: number,\n requestingAccountId: string,\n feeConfig?: FeeConfigBuilderInterface\n ): Promise<{ success: boolean; connectionTopicId?: string; error?: string }> {\n try {\n const inboundTopicId = await this.hcsClient.getInboundTopicId();\n this.logger.info(\n `Accepting connection request #${connectionRequestId} from ${requestingAccountId}`\n );\n\n const result = await this.hcsClient.handleConnectionRequest(\n inboundTopicId,\n requestingAccountId,\n connectionRequestId,\n feeConfig\n );\n\n if (!result?.connectionTopicId) {\n return {\n success: false,\n error: 'Connection acceptance returned no connection topic ID',\n };\n }\n\n const connectionTopicId = result.connectionTopicId;\n this.logger.info(\n `Connection established! Topic ID: ${connectionTopicId}`\n );\n\n let profileInfo: AIAgentProfile | undefined;\n try {\n const profile = await this.hcsClient.getAgentProfile(\n requestingAccountId\n );\n if (profile.success && profile.profile) {\n profileInfo = profile.profile;\n }\n } catch (profileError) {\n this.logger.warn(\n `Could not fetch profile for ${requestingAccountId}: ${profileError}`\n );\n }\n\n const targetInboundTopicId =\n (await this.hcsClient.getAgentProfile(requestingAccountId))?.topicInfo\n ?.inboundTopic || '';\n\n const connection: ActiveConnection = {\n targetAccountId: requestingAccountId,\n targetAgentName:\n profileInfo?.display_name || `Agent ${requestingAccountId}`,\n targetInboundTopicId,\n connectionTopicId,\n profileInfo,\n created: new Date(),\n status: 'established',\n metadata: {\n requestId: connectionRequestId,\n },\n };\n\n this.stateManager.addActiveConnection(connection);\n\n return {\n success: true,\n connectionTopicId,\n };\n } catch (error) {\n this.logger.error(`Error accepting connection request: ${error}`);\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n }\n\n private formatFeeString(\n hbarFees: FeeDefinition[] = [],\n tokenFees: TokenFeeDefinition[] = []\n ): string {\n if (hbarFees.length === 0 && tokenFees.length === 0) {\n return '';\n }\n\n let feeString = ' with fees: ';\n\n if (hbarFees.length > 0) {\n const hbarFeeDetails = hbarFees\n .filter((fee) => fee.amount > 0)\n .map((fee) => {\n const collector = fee.collectorAccount\n ? ` to ${fee.collectorAccount}`\n : '';\n return `${fee.amount} HBAR${collector}`;\n })\n .join(', ');\n\n if (hbarFeeDetails) {\n feeString += hbarFeeDetails;\n }\n }\n\n if (tokenFees.length > 0) {\n if (hbarFees.length > 0) {\n feeString += ' and ';\n }\n\n const tokenFeeDetails = tokenFees\n .filter((fee) => fee.amount > 0 && fee.tokenId)\n .map((fee) => {\n const collector = fee.collectorAccount\n ? ` to ${fee.collectorAccount}`\n : '';\n return `${fee.amount} of token ${fee.tokenId}${collector}`;\n })\n .join(', ');\n\n if (tokenFeeDetails) {\n feeString += tokenFeeDetails;\n }\n }\n\n return feeString === ' with fees: ' ? '' : feeString;\n }\n\n /**\n * Updates the ConnectionsManager with latest connection data\n * This method is meant to be called when changes to connections happen\n * outside this tool's monitoring process\n */\n public update(): void {\n // Trigger the listConnectionsTool to refresh state data\n this.listConnectionsTool\n .invoke({\n includeDetails: true,\n showPending: true,\n })\n .catch((error) => {\n this.logger.error(`Error updating connections: ${error}`);\n });\n }\n}\n","import { StructuredTool, ToolParams } from '@langchain/core/tools';\nimport { z } from 'zod';\nimport { HCS10Client } from '../hcs10/HCS10Client';\nimport { IStateManager } from '../state/state-types';\nimport { Logger } from '@hashgraphonline/standards-sdk';\n\nexport interface ManageConnectionRequestsToolParams extends ToolParams {\n hcsClient: HCS10Client;\n stateManager: IStateManager;\n}\n\n/**\n * A tool for managing incoming connection requests in a LangChain-compatible way.\n * This tool allows an agent to list, view details of, and accept/reject incoming connection requests.\n */\nexport class ManageConnectionRequestsTool extends StructuredTool {\n name = 'manage_connection_requests';\n description =\n 'Manage incoming connection requests. List pending requests, view details about requesting agents, and reject connection requests. Use the separate \"accept_connection_request\" tool to accept.';\n schema = z.object({\n action: z\n .enum(['list', 'view', 'reject'])\n .describe(\n 'The action to perform: list all requests, view details of a specific request, or reject a request'\n ),\n requestKey: z\n .string()\n .optional()\n .describe(\n 'The unique request key to view or reject (required for view and reject actions)'\n ),\n });\n\n private hcsClient: HCS10Client;\n private stateManager: IStateManager;\n private logger: Logger;\n private lastRefreshTime: number = 0;\n private refreshIntervalMs = 30000;\n\n constructor({\n hcsClient,\n stateManager,\n ...rest\n }: ManageConnectionRequestsToolParams) {\n super(rest);\n this.hcsClient = hcsClient;\n this.stateManager = stateManager;\n this.logger = Logger.getInstance({\n module: 'ManageConnectionRequestsTool',\n level: 'debug',\n });\n }\n\n protected async _call({\n action,\n requestKey,\n }: z.infer<this['schema']>): Promise<string> {\n const currentAgent = this.stateManager.getCurrentAgent();\n if (!currentAgent) {\n return 'Error: Cannot manage connection requests. No agent is currently active. Please register or select an agent first.';\n }\n\n if ((action === 'view' || action === 'reject') && requestKey === undefined) {\n return `Error: Request key is required for the \"${action}\" action. Use the \"list\" action first to see available requests.`;\n }\n\n try {\n await this.refreshRequestsIfNeeded();\n\n switch (action) {\n case 'list':\n return this.listRequests();\n case 'view':\n return this.viewRequest(requestKey!);\n case 'reject':\n return this.rejectRequest(requestKey!);\n default:\n return `Error: Unsupported action: ${action}`;\n }\n } catch (error) {\n this.logger.error(`Error in ManageConnectionRequestsTool: ${error}`);\n return `Error managing connection requests: ${\n error instanceof Error ? error.message : String(error)\n }`;\n }\n }\n\n private async refreshRequestsIfNeeded(): Promise<void> {\n const now = Date.now();\n if (now - this.lastRefreshTime > this.refreshIntervalMs) {\n await this.refreshRequests();\n this.lastRefreshTime = now;\n }\n }\n\n private async refreshRequests(): Promise<void> {\n try {\n const { accountId } = this.hcsClient.getAccountAndSigner();\n if (!accountId) {\n throw new Error('Could not determine account ID for current agent');\n }\n\n const connectionManager = this.stateManager.getConnectionsManager();\n if (!connectionManager) {\n throw new Error('ConnectionsManager not initialized');\n }\n\n await connectionManager.fetchConnectionData(accountId);\n } catch (error) {\n this.logger.error(`Error refreshing connection requests: ${error}`);\n throw error;\n }\n }\n\n private listRequests(): string {\n const connectionsManager = this.stateManager.getConnectionsManager();\n if (!connectionsManager) {\n return 'Error: ConnectionsManager not initialized';\n }\n\n const pendingRequests = connectionsManager.getPendingRequests();\n const needsConfirmation =\n connectionsManager.getConnectionsNeedingConfirmation();\n\n const allRequests = [...pendingRequests, ...needsConfirmation];\n\n if (allRequests.length === 0) {\n console.log('No pending connection requests found.', allRequests);\n return 'No pending connection requests found.';\n }\n\n let output = `Found ${allRequests.length} pending connection request(s):\\n\\n`;\n const sortedRequests = [...allRequests].sort(\n (a, b) => b.created.getTime() - a.created.getTime()\n );\n\n sortedRequests.forEach((request, index) => {\n // Create a display ID for the connection request\n const requestType = request.needsConfirmation ? '🟠 Incoming' : '⚪️ Outgoing';\n const requestIdDisplay = request.uniqueRequestKey ||\n `${request.connectionRequestId || request.inboundRequestId || 'unknown'}`;\n\n output += `${index + 1}. ${requestType} - Key: ${requestIdDisplay}\\n`;\n output += ` ${request.needsConfirmation ? 'From' : 'To'}: ${\n request.targetAgentName || `Agent ${request.targetAccountId}`\n } (${request.targetAccountId})\\n`;\n output += ` Sent/Rcvd: ${request.created.toLocaleString()}\\n`;\n\n if (request.memo) {\n output += ` Memo: ${request.memo}\\n`;\n }\n\n if (request.profileInfo && request.profileInfo.bio) {\n output += ` Bio: ${request.profileInfo.bio}\\n`;\n }\n\n output += '\\n';\n });\n\n output +=\n 'To view more details about a request, use action=\"view\" with the specific requestKey.\\n';\n output +=\n 'To reject a request, use action=\"reject\" with the specific requestKey.';\n return output;\n }\n\n private viewRequest(requestKey: string): string {\n const connectionsManager = this.stateManager.getConnectionsManager();\n if (!connectionsManager) {\n return 'Error: ConnectionsManager not initialized';\n }\n\n const pendingRequests = connectionsManager.getPendingRequests();\n const needsConfirmation =\n connectionsManager.getConnectionsNeedingConfirmation();\n\n const allRequests = [...pendingRequests, ...needsConfirmation];\n\n // Find the request with the matching unique key or fallback to sequence number\n const request = allRequests.find(\n (r) =>\n (r.uniqueRequestKey === requestKey) ||\n (r.connectionRequestId?.toString() === requestKey) ||\n (r.inboundRequestId?.toString() === requestKey)\n );\n\n if (!request) {\n return `Error: Request with key ${requestKey} not found or no longer pending.`;\n }\n\n // Create a display ID for the connection request\n const requestType = request.needsConfirmation ? 'Incoming' : 'Outgoing';\n const uniqueKey = request.uniqueRequestKey ||\n `${request.connectionRequestId || request.inboundRequestId || 'unknown'}`;\n\n let output = `Details for ${requestType} connection request: ${uniqueKey}\\n\\n`;\n output += `${request.needsConfirmation ? 'Requestor' : 'Target'} ID: ${request.targetAccountId}\\n`;\n output += `${request.needsConfirmation ? 'Requestor' : 'Target'} Name: ${\n request.targetAgentName || `Agent ${request.targetAccountId}`\n }\\n`;\n output += `Received: ${request.created.toLocaleString()}\\n`;\n\n if (request.memo) {\n output += `Memo: ${request.memo}\\n`;\n }\n\n if (request.profileInfo) {\n output += '\\nAgent Profile Information:\\n';\n\n if (request.profileInfo.display_name || request.profileInfo.alias) {\n output += `Name: ${\n request.profileInfo.display_name || request.profileInfo.alias\n }\\n`;\n }\n\n if (request.profileInfo.type !== undefined) {\n output += `Type: ${request.profileInfo.type}\\n`;\n }\n\n if (request.profileInfo.bio) {\n output += `Bio: ${request.profileInfo.bio}\\n`;\n }\n }\n\n output += '\\nActions:\\n';\n output += `- To reject this request: action=\"reject\", requestKey=\"${uniqueKey}\"\\n`;\n output +=\n 'Use the separate \"accept_connection_request\" tool to accept requests.';\n return output;\n }\n\n private async rejectRequest(requestKey: string): Promise<string> {\n const connectionsManager = this.stateManager.getConnectionsManager();\n if (!connectionsManager) {\n return 'Error: ConnectionsManager not initialized';\n }\n\n const pendingRequests = connectionsManager.getPendingRequests();\n const needsConfirmation =\n connectionsManager.getConnectionsNeedingConfirmation();\n\n const allRequests = [...pendingRequests, ...needsConfirmation];\n\n // Find the request with the matching unique key or fallback to sequence number\n const request = allRequests.find(\n (r) =>\n (r.uniqueRequestKey === requestKey) ||\n (r.connectionRequestId?.toString() === requestKey) ||\n (r.inboundRequestId?.toString() === requestKey)\n );\n\n if (!request) {\n return `Error: Request with key ${requestKey} not found or no longer pending.`;\n }\n\n // Mark as processed in ConnectionsManager based on the appropriate ID\n if (request.inboundRequestId) {\n // For needs_confirmation requests\n connectionsManager.markConnectionRequestProcessed(\n request.targetInboundTopicId || '',\n request.inboundRequestId\n );\n } else if (request.connectionRequestId) {\n // For pending requests\n connectionsManager.markConnectionRequestProcessed(\n request.originTopicId || '',\n request.connectionRequestId\n );\n }\n\n return `Connection request from ${\n request.targetAgentName || `Agent ${request.targetAccountId}`\n } was rejected.`;\n }\n}\n","import { StructuredTool, ToolParams } from '@langchain/core/tools';\nimport { z } from 'zod';\nimport { HCS10Client } from '../hcs10/HCS10Client';\nimport { IStateManager, ActiveConnection } from '../state/state-types';\nimport { Logger, FeeConfigBuilder } from '@hashgraphonline/standards-sdk';\n\nexport interface AcceptConnectionRequestToolParams extends ToolParams {\n hcsClient: HCS10Client;\n stateManager: IStateManager;\n}\n\n/**\n * A tool specifically for accepting incoming connection requests.\n */\nexport class AcceptConnectionRequestTool extends StructuredTool {\n name = 'accept_connection_request';\n description =\n 'Accepts a specific pending connection request from another agent, establishing a communication channel.';\n schema = z.object({\n requestKey: z\n .string()\n .describe(\n 'The unique request key of the specific request to accept. Use the \"manage_connection_requests\" tool with action=\"list\" first to get valid keys.'\n ),\n hbarFee: z\n .number()\n .optional()\n .describe(\n 'Optional HBAR fee amount to charge the connecting agent per message on the new connection topic.'\n ),\n exemptAccountIds: z\n .array(z.string())\n .optional()\n .describe(\n 'Optional list of account IDs to exempt from any configured fees on the new connection topic.'\n ),\n });\n\n private hcsClient: HCS10Client;\n private stateManager: IStateManager;\n private logger: Logger;\n\n constructor({\n hcsClient,\n stateManager,\n ...rest\n }: AcceptConnectionRequestToolParams) {\n super(rest);\n this.hcsClient = hcsClient;\n this.stateManager = stateManager;\n this.logger = Logger.getInstance({\n module: 'AcceptConnectionRequestTool',\n });\n }\n\n protected async _call({\n requestKey,\n hbarFee,\n exemptAccountIds,\n }: z.infer<this['schema']>): Promise<string> {\n const currentAgent = this.stateManager.getCurrentAgent();\n if (!currentAgent) {\n return 'Error: Cannot accept connection request. No agent is currently active. Please register or select an agent first.';\n }\n\n const connectionsManager = this.stateManager.getConnectionsManager();\n if (!connectionsManager) {\n return 'Error: ConnectionsManager not initialized';\n }\n\n await connectionsManager.fetchConnectionData(currentAgent.accountId);\n\n // Find the request with the matching unique key or fallback to sequence number\n const allRequests = [\n ...connectionsManager.getPendingRequests(),\n ...connectionsManager.getConnectionsNeedingConfirmation()\n ];\n\n const request = allRequests.find(\n (r) => (r.uniqueRequestKey === requestKey) ||\n (r.connectionRequestId?.toString() === requestKey) ||\n (r.inboundRequestId?.toString() === requestKey)\n );\n\n if (!request) {\n return `Error: Request with key ${requestKey} not found or no longer pending. Use the manage_connection_requests tool with action=\"list\" to verify.`;\n }\n\n // Get the numeric request ID from the request for the SDK call\n const numericRequestId = request.connectionRequestId || request.inboundRequestId;\n if (!numericRequestId) {\n return `Error: Could not determine a valid request ID for the request with key ${requestKey}.`;\n }\n\n try {\n const inboundTopicId = await this.hcsClient.getInboundTopicId();\n let feeConfigBuilder = undefined;\n\n if (hbarFee && hbarFee > 0) {\n const collectorId = this.hcsClient.getAccountAndSigner().accountId;\n try {\n feeConfigBuilder = new FeeConfigBuilder({\n network: this.hcsClient.getNetwork(),\n logger: this.logger,\n defaultCollectorAccountId: collectorId,\n });\n\n const finalExemptions = [\n ...(exemptAccountIds || []),\n currentAgent.accountId,\n ];\n feeConfigBuilder.addHbarFee(hbarFee, collectorId, finalExemptions);\n this.logger.info(\n `Setting HBAR fee: ${hbarFee} HBAR to be collected by ${collectorId}`\n );\n } catch (feeConfigError) {\n this.logger.error(\n `Error creating fee configuration: ${feeConfigError}`\n );\n\n feeConfigBuilder = undefined;\n this.logger.warn(\n 'Proceeding to accept request without fees due to configuration error.'\n );\n }\n }\n\n this.logger.info(\n `Attempting to accept request Key: ${requestKey} (ID: ${numericRequestId}) from ${request.targetAccountId}`\n );\n const result = await this.hcsClient.handleConnectionRequest(\n inboundTopicId,\n request.targetAccountId,\n numericRequestId,\n feeConfigBuilder\n );\n\n if (!result?.connectionTopicId) {\n return `Error: Failed to accept connection request with key ${requestKey}. The SDK did not return a connection topic ID.`;\n }\n this.logger.info(\n `Successfully created connection topic: ${result.connectionTopicId}`\n );\n\n const connectionTopicId = result.connectionTopicId;\n\n let targetInboundTopic = '';\n try {\n const targetProfileData = await this.hcsClient.standardClient.retrieveProfile(request.targetAccountId);\n targetInboundTopic =\n targetProfileData?.topicInfo?.inboundTopic || '';\n if (!targetInboundTopic) {\n this.logger.warn(\n `Could not resolve target inbound topic for ${request.targetAccountId}`\n );\n }\n } catch (e) {\n this.logger.warn(\n `Error fetching target profile/topic for ${request.targetAccountId}: ${e}`\n );\n }\n\n const name = request.profileInfo?.display_name || request.profileInfo?.alias || `Agent ${request.targetAccountId}`;\n const newConnection: ActiveConnection = {\n targetAccountId: request.targetAccountId,\n targetAgentName: name,\n targetInboundTopicId: targetInboundTopic,\n connectionTopicId,\n profileInfo: request.profileInfo,\n created: new Date(),\n status: 'established',\n };\n\n this.stateManager.addActiveConnection(newConnection);\n connectionsManager.fetchConnectionData(request.targetAccountId);\n\n this.logger.info(`Removed request ${requestKey} from pending requests`);\n\n let feeMessage = '';\n if (hbarFee && hbarFee > 0 && feeConfigBuilder) {\n feeMessage = ` with a ${hbarFee} HBAR fee per message`;\n }\n\n const displayKey = request.uniqueRequestKey || requestKey;\n return `Successfully accepted connection request ${displayKey} from ${name} ${feeMessage}. Connection established on topic: ${connectionTopicId}.`;\n } catch (error) {\n this.logger.error(\n `Error accepting connection request ${requestKey}: ${error}`\n );\n\n return `Error accepting connection request ${requestKey}: ${\n error instanceof Error ? error.message : String(error)\n }`;\n }\n }\n}\n","import { StructuredTool } from '@langchain/core/tools';\nimport { z } from 'zod';\nimport { HCS10Client } from '../hcs10/HCS10Client';\nimport { Logger } from '@hashgraphonline/standards-sdk';\n\n/**\n * Tool for retrieving the HCS-11 profile associated with a Hedera account ID.\n * Utilizes the HCS10Client's retrieveProfile method, which handles fetching.\n */\nexport class RetrieveProfileTool extends StructuredTool {\n name = 'retrieve_profile';\n description =\n 'Retrieves the HCS-11 profile data associated with a given Hedera account ID. If no account ID is provided, it defaults to the current operator account ID. Returns the profile object as a JSON string on success.';\n\n private client: HCS10Client;\n private logger: Logger;\n\n schema = z.object({\n accountId: z\n .string()\n .optional()\n .describe(\n 'The Hedera account ID (e.g., 0.0.12345) to retrieve the profile for. If omitted, defaults to the current operator account ID.'\n ),\n disableCache: z\n .boolean()\n .optional()\n .describe(\n 'Optional: Set to true to bypass the cache and fetch fresh profile data.'\n ),\n });\n\n /**\n * Creates a new RetrieveProfileTool instance.\n * @param client - An instance of HCS10Client.\n */\n constructor(client: HCS10Client) {\n super();\n this.client = client;\n this.logger = Logger.getInstance({ module: this.name });\n }\n\n /**\n * Executes the profile retrieval.\n * @param input - The input object containing accountId and optional disableCache flag.\n * @returns A JSON string of the profile on success, or an error message string.\n */\n async _call(input: z.infer<typeof this.schema>): Promise<string> {\n let targetAccountId: string;\n try {\n if (input.accountId) {\n targetAccountId = input.accountId;\n } else {\n this.logger.info('accountId not provided, defaulting to operator ID.');\n targetAccountId = this.client.getOperatorId();\n }\n\n if (!targetAccountId) {\n throw new Error('Could not determine target account ID.');\n }\n\n this.logger.info(\n `Attempting to retrieve profile for account: ${targetAccountId}, Disable Cache: ${!!input.disableCache}`\n );\n\n // Call retrieveProfile via the standardClient instance using the determined ID\n const result = await this.client.standardClient.retrieveProfile(\n targetAccountId,\n input.disableCache\n );\n\n if (result.success && result.profile) {\n this.logger.info(\n `Successfully retrieved profile for ${targetAccountId}.`\n );\n\n return JSON.stringify(result.profile, null, 2);\n } else {\n const errorMessage = `Error retrieving profile for ${targetAccountId}: ${\n result.error || 'Profile not found or invalid.'\n }`;\n this.logger.error(errorMessage);\n return errorMessage;\n }\n } catch (error) {\n const idForError = input.accountId || 'operator default';\n const errorMessage = `Unexpected error retrieving profile for ${idForError}: ${\n error instanceof Error ? error.message : String(error)\n }`;\n this.logger.error(errorMessage, error);\n return errorMessage;\n }\n }\n}\n","import { StructuredTool, ToolParams } from '@langchain/core/tools';\nimport { z } from 'zod';\nimport {\n IStateManager,\n} from '../state/state-types';\nimport { HCS10Client } from '../hcs10/HCS10Client';\nimport {\n Logger,\n Connection,\n} from '@hashgraphonline/standards-sdk';\n\n\ntype ListPendingRequestsToolParams = ToolParams & {\n hcsClient: HCS10Client;\n stateManager: IStateManager;\n};\n\nexport class ListUnapprovedConnectionRequestsTool extends StructuredTool {\n name = 'list_unapproved_connection_requests';\n description =\n 'Lists all connection requests that are not fully established, including incoming requests needing approval and outgoing requests waiting for confirmation.';\n schema = z.object({\n sortBy: z\n .enum(['time_asc', 'time_desc', 'name_asc', 'name_desc'])\n .optional()\n .describe(\n 'Optional sorting criteria for the requests list (default: time_desc, newest first)'\n ),\n limit: z\n .number()\n .optional()\n .describe(\n 'Optional limit on the number of requests to return (default: all)'\n ),\n });\n\n private hcsClient: HCS10Client;\n private stateManager: IStateManager;\n private logger: Logger;\n\n constructor({\n hcsClient,\n stateManager,\n ...rest\n }: ListPendingRequestsToolParams) {\n super(rest);\n this.hcsClient = hcsClient;\n this.stateManager = stateManager;\n this.logger = Logger.getInstance({\n module: 'ListPendingRequestsTool',\n level: 'debug',\n });\n }\n\n protected async _call({\n sortBy = 'time_desc',\n limit,\n }: z.infer<this['schema']>): Promise<string> {\n const currentAgent = this.stateManager.getCurrentAgent();\n if (!currentAgent) {\n return 'Error: Cannot list pending requests. No agent is currently active. Please register or select an agent first.';\n }\n\n try {\n const pendingRequests = await this.findAllPendingRequests();\n return this.formatRequestsList(pendingRequests, sortBy, limit);\n } catch (error) {\n this.logger.error(`Error in ${this.name}: ${error}`);\n return `Error listing pending requests: ${\n error instanceof Error ? error.message : String(error)\n }`;\n }\n }\n\n /**\n * Processes the connection connectionMap to find all requests\n * that are not fully established (incoming unapproved and outgoing pending).\n */\n private async findAllPendingRequests(): Promise<Connection[]> {\n const connectionsManager = this.stateManager.getConnectionsManager();\n if (!connectionsManager) {\n return [];\n }\n const currentAgent = this.stateManager.getCurrentAgent();\n if (!currentAgent) {\n return [];\n }\n\n await connectionsManager.fetchConnectionData(currentAgent.accountId);\n const pendingRequests = connectionsManager.getPendingRequests();\n const connectionsNeedingConfirmation = connectionsManager.getConnectionsNeedingConfirmation();\n\n return [...pendingRequests, ...connectionsNeedingConfirmation];\n }\n\n /**\n * Formats the list of pending requests for display.\n */\n private formatRequestsList(\n requests: Connection[],\n sortBy: string,\n limit?: number\n ): string {\n if (requests.length === 0) {\n return 'No pending connection requests found (incoming or outgoing).';\n }\n\n const sortedRequests = this.sortRequests(requests, sortBy);\n const limitedRequests = limit\n ? sortedRequests.slice(0, limit)\n : sortedRequests;\n\n let output = `Found ${requests.length} pending connection request(s):\\n\\n`;\n\n limitedRequests.forEach((request, index) => {\n const statusIndicator =\n request.status === 'needs_confirmation'\n ? '🟠 Incoming'\n : '⚪️ Outgoing';\n output += `${index + 1}. ${statusIndicator} - ID: ${request.uniqueRequestKey}\\n`;\n output += ` ${\n request.status === 'needs_confirmation' ? 'From:' : 'To: '\n } ${request.targetAgentName} (${request.targetAccountId})\\n`;\n output += ` Sent/Rcvd: ${request.created.toLocaleString()}\\n`;\n if (request.memo) {\n output += ` Memo: ${request.memo}\\n`;\n }\n if (request.profileInfo?.bio) {\n output += ` Bio: ${request.profileInfo.bio.substring(0, 100)}${\n request.profileInfo.bio.length > 100 ? '...' : ''\n }\\n`;\n }\n output += '\\n';\n });\n\n output +=\n 'Use related tools (manage_requests, accept_request) to handle these items.';\n return output;\n }\n\n /**\n * Sorts connection requests based on the specified criteria.\n */\n private sortRequests(\n requests: Connection[],\n sortBy: string\n ): Connection[] {\n const requestsCopy = [...requests];\n\n switch (sortBy) {\n case 'time_asc':\n return requestsCopy.sort(\n (a, b) => a.created.getTime() - b.created.getTime()\n );\n case 'time_desc':\n return requestsCopy.sort(\n (a, b) => b.created.getTime() - a.created.getTime()\n );\n case 'name_asc':\n return requestsCopy.sort((a, b) =>\n a.targetAgentName?.localeCompare(b?.targetAgentName || '') || 0\n );\n case 'name_desc':\n return requestsCopy.sort((a, b) =>\n b.targetAgentName?.localeCompare(a?.targetAgentName || '') || 0\n );\n default:\n return requestsCopy.sort(\n (a, b) => b.created.getTime() - a.created.getTime()\n );\n }\n }\n}\n","import {\n HCS10Client,\n AgentBuilder,\n Logger,\n} from '@hashgraphonline/standards-sdk';\nimport fs from 'fs';\nimport path from 'path';\nimport { ensureAgentHasEnoughHbar } from './ensure-agent-has-hbar';\n\nexport const ENV_FILE_PATH = path.join(process.cwd(), '.env');\n\nexport interface AgentData {\n accountId: string;\n operatorId: string;\n inboundTopicId: string;\n outboundTopicId: string;\n client: HCS10Client;\n}\n\nexport interface RegistrationProgressData {\n registered: boolean;\n accountId?: string;\n privateKey?: string;\n publicKey?: string;\n inboundTopicId?: string;\n outboundTopicId?: string;\n}\n\nexport async function getAgentFromEnv(\n logger: Logger,\n baseClient: HCS10Client,\n agentName: string,\n envPrefix: string\n): Promise<AgentData | null> {\n const accountIdEnvVar = `${envPrefix}_ACCOUNT_ID`;\n const privateKeyEnvVar = `${envPrefix}_PRIVATE_KEY`;\n const inboundTopicIdEnvVar = `${envPrefix}_INBOUND_TOPIC_ID`;\n const outboundTopicIdEnvVar = `${envPrefix}_OUTBOUND_TOPIC_ID`;\n\n const accountId = process.env[accountIdEnvVar];\n const privateKey = process.env[privateKeyEnvVar];\n const inboundTopicId = process.env[inboundTopicIdEnvVar];\n const outboundTopicId = process.env[outboundTopicIdEnvVar];\n\n if (!accountId || !privateKey || !inboundTopicId || !outboundTopicId) {\n logger.info(`${agentName} agent not found in environment variables`);\n return null;\n }\n\n logger.info(`${agentName} agent found in environment variables`);\n logger.info(`${agentName} account ID: ${accountId}`);\n logger.info(`${agentName} inbound topic ID: ${inboundTopicId}`);\n logger.info(`${agentName} outbound topic ID: ${outboundTopicId}`);\n\n const client = new HCS10Client({\n network: 'testnet',\n operatorId: accountId,\n operatorPrivateKey: privateKey,\n guardedRegistryBaseUrl: process.env.REGISTRY_URL,\n prettyPrint: true,\n logLevel: 'debug',\n });\n\n await ensureAgentHasEnoughHbar(logger, baseClient, accountId, agentName);\n\n return {\n accountId,\n operatorId: `${inboundTopicId}@${accountId}`,\n inboundTopicId,\n outboundTopicId,\n client,\n };\n}\n\nexport async function createAgent(\n logger: Logger,\n baseClient: HCS10Client,\n agentName: string,\n agentBuilder: AgentBuilder,\n envPrefix: string\n): Promise<AgentData | null> {\n try {\n logger.info(`Creating ${agentName} agent...`);\n\n const result = await baseClient.createAndRegisterAgent(agentBuilder);\n\n if (!result.metadata) {\n logger.error(`${agentName} agent creation failed`);\n return null;\n }\n\n logger.info(`${agentName} agent created successfully`);\n logger.info(`${agentName} account ID: ${result.metadata.accountId}`);\n logger.info(`${agentName} private key: ${result.metadata.privateKey}`);\n logger.info(\n `${agentName} inbound topic ID: ${result.metadata.inboundTopicId}`\n );\n logger.info(\n `${agentName} outbound topic ID: ${result.metadata.outboundTopicId}`\n );\n\n const envVars = {\n [`${envPrefix}_ACCOUNT_ID`]: result.metadata.accountId,\n [`${envPrefix}_PRIVATE_KEY`]: result.metadata.privateKey,\n [`${envPrefix}_INBOUND_TOPIC_ID`]: result.metadata.inboundTopicId,\n [`${envPrefix}_OUTBOUND_TOPIC_ID`]: result.metadata.outboundTopicId,\n };\n\n await updateEnvFile(ENV_FILE_PATH, envVars);\n\n const client = new HCS10Client({\n network: 'testnet',\n operatorId: result.metadata.accountId,\n operatorPrivateKey: result.metadata.privateKey,\n guardedRegistryBaseUrl: process.env.REGISTRY_URL,\n prettyPrint: true,\n logLevel: 'debug',\n });\n\n return {\n accountId: result.metadata.accountId,\n operatorId: `${result.metadata.inboundTopicId}@${result.metadata.accountId}`,\n inboundTopicId: result.metadata.inboundTopicId,\n outboundTopicId: result.metadata.outboundTopicId,\n client,\n };\n } catch (error) {\n console.log('error', error, baseClient);\n logger.error(`Error creating ${agentName} agent:`, error);\n return null;\n }\n}\n\nexport async function updateEnvFile(\n envFilePath: string,\n variables: Record<string, string>\n): Promise<void> {\n let envContent = '';\n\n if (fs.existsSync(envFilePath)) {\n envContent = fs.readFileSync(envFilePath, 'utf8');\n }\n\n const envLines = envContent.split('\\n');\n const updatedLines = [...envLines];\n\n for (const [key, value] of Object.entries(variables)) {\n const lineIndex = updatedLines.findIndex((line) =>\n line.startsWith(`${key}=`)\n );\n\n if (lineIndex !== -1) {\n updatedLines[lineIndex] = `${key}=${value}`;\n } else {\n updatedLines.push(`${key}=${value}`);\n }\n }\n\n fs.writeFileSync(envFilePath, updatedLines.join('\\n'));\n}\n","import { updateEnvFile } from '../utils/state-tools';\nimport {\n RegisteredAgent,\n ActiveConnection,\n IStateManager,\n AgentPersistenceOptions,\n EnvFilePersistenceOptions,\n ConnectionStatus,\n} from './state-types';\nimport {\n ConnectionsManager,\n HCS10BaseClient,\n Connection,\n Logger,\n IConnectionsManager,\n} from '@hashgraphonline/standards-sdk';\n\n/**\n * Implementation of the IStateManager interface for the OpenConvai system.\n * Manages agent state and connection information with thread safety and\n * proper timestamp tracking.\n */\nexport class OpenConvaiState implements IStateManager {\n private currentAgent: RegisteredAgent | null = null;\n private connectionMessageTimestamps: Record<string, number> = {};\n private defaultEnvFilePath?: string;\n private defaultPrefix: string;\n private connectionsManager: IConnectionsManager | null = null;\n private logger: Logger;\n\n /**\n * Creates a new OpenConvaiState instance\n * @param options - Options for environment variable persistence\n */\n constructor(options?: {\n defaultEnvFilePath?: string;\n defaultPrefix?: string;\n baseClient?: HCS10BaseClient;\n disableLogging?: boolean;\n }) {\n this.defaultEnvFilePath = options?.defaultEnvFilePath;\n this.defaultPrefix = options?.defaultPrefix ?? 'TODD';\n const shouldSilence = options?.disableLogging || process.env.DISABLE_LOGGING === 'true';\n this.logger = new Logger({ module: 'OpenConvaiState', silent: shouldSilence });\n\n // Initialize ConnectionsManager immediately if baseClient is provided\n if (options?.baseClient) {\n this.initializeConnectionsManager(options.baseClient);\n }\n }\n\n /**\n * Initializes the ConnectionsManager\n * @param baseClient - HCS10BaseClient instance to use\n */\n initializeConnectionsManager(\n baseClient: HCS10BaseClient\n ): IConnectionsManager {\n if (!this.connectionsManager) {\n this.logger.debug('Initializing ConnectionsManager');\n this.connectionsManager = new ConnectionsManager({\n baseClient,\n logLevel: 'error',\n });\n } else {\n this.logger.debug('ConnectionsManager already initialized');\n }\n return this.connectionsManager;\n }\n\n /**\n * Gets the ConnectionsManager instance\n * @returns The ConnectionsManager instance, or null if not initialized\n */\n getConnectionsManager(): IConnectionsManager | null {\n return this.connectionsManager;\n }\n\n /**\n * Sets the current active agent and clears any previous connection data.\n * This should be called when switching between agents.\n */\n setCurrentAgent(agent: RegisteredAgent | null): void {\n this.currentAgent = agent;\n this.connectionMessageTimestamps = {};\n\n // Clear connections manager when changing agents\n if (this.connectionsManager) {\n this.connectionsManager.clearAll();\n }\n }\n\n /**\n * Returns the currently active agent or null if none is set.\n */\n getCurrentAgent(): RegisteredAgent | null {\n return this.currentAgent;\n }\n\n /**\n * Adds a new connection to the active connections list.\n * Ensures no duplicates are added based on connectionTopicId.\n * Initializes timestamp tracking for the connection.\n */\n addActiveConnection(connection: ActiveConnection): void {\n if (!this.connectionsManager) {\n this.logger.error(\n 'ConnectionsManager not initialized. Call initializeConnectionsManager before adding connections.'\n );\n throw new Error(\n 'ConnectionsManager not initialized. Call initializeConnectionsManager before adding connections.'\n );\n }\n\n // Convert from ActiveConnection to Connection\n const sdkConnection: Connection = {\n connectionTopicId: connection.connectionTopicId,\n targetAccountId: connection.targetAccountId,\n targetAgentName: connection.targetAgentName,\n targetInboundTopicId: connection.targetInboundTopicId,\n status: this.convertConnectionStatus(connection.status || 'established'),\n isPending: connection.isPending || false,\n needsConfirmation: connection.needsConfirmation || false,\n created: connection.created || new Date(),\n lastActivity: connection.lastActivity,\n profileInfo: connection.profileInfo,\n connectionRequestId: connection.connectionRequestId,\n processed: true,\n };\n\n // Add to ConnectionsManager\n this.connectionsManager.updateOrAddConnection(sdkConnection);\n\n // Initialize timestamp tracking\n this.initializeTimestampIfNeeded(connection.connectionTopicId);\n }\n\n /**\n * Updates an existing connection or adds it if not found.\n * Preserves existing properties when updating by merging objects.\n */\n updateOrAddConnection(connection: ActiveConnection): void {\n this.addActiveConnection(connection);\n }\n\n /**\n * Returns a copy of all active connections.\n */\n listConnections(): ActiveConnection[] {\n if (!this.connectionsManager) {\n this.logger.debug(\n 'ConnectionsManager not initialized, returning empty connections list'\n );\n return [];\n }\n\n // Convert SDK Connections to ActiveConnection\n return this.connectionsManager\n .getAllConnections()\n .map((conn) => this.convertToActiveConnection(conn));\n }\n\n /**\n * Finds a connection by its identifier, which can be:\n * - A 1-based index as displayed in the connection list\n * - A target account ID string\n * - A connection topic ID string\n */\n getConnectionByIdentifier(identifier: string): ActiveConnection | undefined {\n if (!this.connectionsManager) {\n return undefined;\n }\n\n const connections = this.listConnections();\n\n // Check if it's a 1-based index\n const numericIndex = parseInt(identifier) - 1;\n if (\n !isNaN(numericIndex) &&\n numericIndex >= 0 &&\n numericIndex < connections.length\n ) {\n return connections[numericIndex];\n }\n\n // Check if it's a topic ID\n const byTopicId =\n this.connectionsManager.getConnectionByTopicId(identifier);\n if (byTopicId) {\n return this.convertToActiveConnection(byTopicId);\n }\n\n // Check if it's an account ID\n const byAccountId =\n this.connectionsManager.getConnectionByAccountId(identifier);\n if (byAccountId) {\n return this.convertToActiveConnection(byAccountId);\n }\n\n return undefined;\n }\n\n /**\n * Gets the last processed message timestamp for a connection.\n * Returns 0 if no timestamp has been recorded.\n */\n getLastTimestamp(connectionTopicId: string): number {\n return this.connectionMessageTimestamps[connectionTopicId] || 0;\n }\n\n /**\n * Updates the last processed message timestamp for a connection,\n * but only if the new timestamp is more recent than the existing one.\n */\n updateTimestamp(connectionTopicId: string, timestampNanos: number): void {\n // Initialize if this is first update and skip the comparison logic\n if (!(connectionTopicId in this.connectionMessageTimestamps)) {\n this.connectionMessageTimestamps[connectionTopicId] = timestampNanos;\n return;\n }\n\n // Otherwise, only update if newer\n const currentTimestamp =\n this.connectionMessageTimestamps[connectionTopicId];\n if (timestampNanos > currentTimestamp) {\n this.connectionMessageTimestamps[connectionTopicId] = timestampNanos;\n }\n }\n\n /**\n * Helper method to initialize timestamp tracking for a connection\n * if it doesn't already exist.\n */\n private initializeTimestampIfNeeded(connectionTopicId: string): void {\n if (!(connectionTopicId in this.connectionMessageTimestamps)) {\n this.connectionMessageTimestamps[connectionTopicId] =\n Date.now() * 1_000_000;\n }\n }\n\n /**\n * Converts ConnectionStatus to SDK status format\n */\n private convertConnectionStatus(\n status: string\n ): 'pending' | 'established' | 'needs_confirmation' | 'closed' {\n switch (status) {\n case 'pending':\n return 'pending';\n case 'established':\n return 'established';\n case 'needs confirmation':\n return 'needs_confirmation';\n default:\n return 'established';\n }\n }\n\n /**\n * Converts SDK Connection to ActiveConnection\n */\n private convertToActiveConnection(conn: Connection): ActiveConnection {\n return {\n targetAccountId: conn.targetAccountId,\n targetAgentName: conn.targetAgentName || `Agent ${conn.targetAccountId}`,\n targetInboundTopicId: conn.targetInboundTopicId || '',\n connectionTopicId: conn.connectionTopicId,\n status: this.convertToStateStatus(conn.status),\n created: conn.created,\n lastActivity: conn.lastActivity,\n isPending: conn.isPending,\n needsConfirmation: conn.needsConfirmation,\n profileInfo: conn.profileInfo,\n connectionRequestId: conn.connectionRequestId,\n };\n }\n\n /**\n * Converts SDK status to state status format\n */\n private convertToStateStatus(status: string): ConnectionStatus {\n switch (status) {\n case 'pending':\n return 'pending';\n case 'established':\n return 'established';\n case 'needs_confirmation':\n return 'needs confirmation';\n case 'closed':\n return 'established'; // Mapping closed to established for compatibility\n default:\n return 'unknown';\n }\n }\n\n /**\n * Persists agent data to environment variables\n * @param agent - The agent data to persist\n * @param options - Environment file persistence options\n */\n async persistAgentData(\n agent: RegisteredAgent,\n options?: AgentPersistenceOptions\n ): Promise<void> {\n if (options?.type && options.type !== 'env-file') {\n throw new Error(\n `Unsupported persistence type: ${options.type}. Only 'env-file' is supported.`\n );\n }\n\n const envFilePath =\n (options as EnvFilePersistenceOptions)?.envFilePath ||\n this.defaultEnvFilePath ||\n process.env.ENV_FILE_PATH ||\n '.env';\n\n if (!envFilePath) {\n throw new Error(\n 'Environment file path could not be determined for agent data persistence'\n );\n }\n\n const prefix =\n (options as EnvFilePersistenceOptions)?.prefix || this.defaultPrefix;\n\n if (!agent.accountId || !agent.inboundTopicId || !agent.outboundTopicId) {\n throw new Error('Agent data incomplete, cannot persist to environment');\n }\n\n const updates: Record<string, string> = {\n [`${prefix}_ACCOUNT_ID`]: agent.accountId,\n [`${prefix}_INBOUND_TOPIC_ID`]: agent.inboundTopicId,\n [`${prefix}_OUTBOUND_TOPIC_ID`]: agent.outboundTopicId,\n };\n\n if (agent.privateKey) {\n updates[`${prefix}_PRIVATE_KEY`] = agent.privateKey;\n }\n\n if (agent.profileTopicId) {\n updates[`${prefix}_PROFILE_TOPIC_ID`] = agent.profileTopicId;\n }\n\n await updateEnvFile(envFilePath, updates);\n }\n}\n","import { IPlugin, BasePluginContext } from './PluginInterface';\nimport { StructuredTool } from '@langchain/core/tools';\n\n/**\n * Base class for plugins to simplify implementation\n */\nexport abstract class BasePlugin<T extends BasePluginContext = BasePluginContext> implements IPlugin<T> {\n abstract id: string;\n abstract name: string;\n abstract description: string;\n abstract version: string;\n abstract author: string;\n\n protected context!: T;\n\n /**\n * Initialize the plugin with the provided context\n * @param context The context containing shared resources\n */\n async initialize(context: T): Promise<void> {\n this.context = context;\n }\n\n /**\n * Get the tools provided by this plugin\n * @returns Array of tools provided by this plugin\n */\n abstract getTools(): StructuredTool[];\n\n /**\n * Clean up resources when the plugin is unloaded\n * Default implementation does nothing\n */\n async cleanup(): Promise<void> {\n // Default implementation does nothing\n }\n}\n","import { StructuredTool } from '@langchain/core/tools';\nimport { z } from 'zod';\nimport { IPlugin /*, PluginContext */ } from '../PluginInterface';\nimport axios from 'axios'; // Use axios instead of node-fetch\n\nconst HEDERA_MIRROR_NODE_API = 'https://mainnet.mirrornode.hedera.com/api/v1';\n\n/**\n * Defines the schema for the HBAR price API response.\n */\nconst ExchangeRateResponseSchema = z.object({\n current_rate: z.object({\n cent_equivalent: z.number(),\n hbar_equivalent: z.number(),\n expiration_time: z.number(),\n }),\n next_rate: z.object({\n cent_equivalent: z.number(),\n hbar_equivalent: z.number(),\n expiration_time: z.number(),\n }),\n timestamp: z.string(),\n});\n\n/**\n * A Langchain tool to get the current HBAR price in USD.\n */\n// Export the class for testing purposes\nexport class GetHbarPriceTool extends StructuredTool {\n name = 'getHbarPrice';\n description = 'Retrieves the current price of HBAR in USD from the Hedera Mirror Node.';\n schema = z.object({}); // No input required for this tool\n\n /**\n * DISCLAIMER: THIS TOOL USES THE EXCHANGE RATE ENDPOINT FROM THE MIRROR NODE, AND IT IS NOT GUARANTEED TO BE ACCURATE.\n * USE AN ORACLE OR OTHER SOURCES FOR PRODUCTION USE WHERE PRICE IS IMPORTANT.\n * Retrieves the current price of HBAR in USD from the Hedera Mirror Node.\n * @returns A promise that resolves to a string containing the current HBAR price in USD.\n */\n protected async _call(): Promise<string> {\n try {\n // Use axios.get instead of fetch\n const response = await axios.get(`${HEDERA_MIRROR_NODE_API}/network/exchangerate`);\n\n // Axios puts data directly in response.data\n const data: unknown = response.data;\n\n // Validate the response structure\n const parsedData = ExchangeRateResponseSchema.safeParse(data);\n if (!parsedData.success) {\n console.error(\"Failed to parse exchange rate response:\", parsedData.error);\n throw new Error('Invalid API response format');\n }\n\n const { current_rate } = parsedData.data;\n const priceUsd = current_rate.cent_equivalent / current_rate.hbar_equivalent / 100;\n\n return `The current price of HBAR is $${priceUsd.toFixed(6)} USD.`;\n } catch (error) {\n console.error('Error fetching HBAR price:', error);\n // Handle axios errors specifically if needed, otherwise generic handling\n let errorMessage = 'An unknown error occurred';\n if (axios.isAxiosError(error)) {\n errorMessage = error.message;\n if (error.response) {\n errorMessage += ` (Status: ${error.response.status})`;\n }\n } else if (error instanceof Error) {\n errorMessage = error.message;\n }\n return `Failed to retrieve HBAR price: ${errorMessage}`;\n }\n }\n}\n\n\n/**\n * DISCLAIMER: THIS PLUGIN USES THE EXCHANGE RATE ENDPOINT FROM THE MIRROR NODE, AND IT IS NOT GUARANTEED TO BE ACCURATE.\n * USE AN ORACLE OR OTHER SOURCES FOR PRODUCTION USE WHERE PRICE IS IMPORTANT.\n * Plugin to provide tools related to Hedera network information, like HBAR price.\n */\nexport class HbarPricePlugin implements IPlugin {\n id = 'hedera-hbar-price';\n name = 'Hedera HBAR Price Plugin';\n description = 'Provides tools to interact with Hedera network data, specifically HBAR price.';\n version = '1.0.0';\n author = 'Hedera Agent'; // Replace with actual author/team name if desired\n\n private tools: StructuredTool[];\n\n constructor() {\n this.tools = [new GetHbarPriceTool()];\n }\n\n /**\n * Initializes the plugin. Currently no specific initialization needed.\n */\n async initialize(): Promise<void> {\n // No specific initialization required for this plugin yet\n return Promise.resolve();\n }\n\n /**\n * Returns the tools provided by this plugin.\n * @returns An array containing the GetHbarPriceTool.\n */\n getTools(): StructuredTool[] {\n return this.tools;\n }\n\n /**\n * Cleans up resources. Currently no cleanup needed.\n */\n async cleanup(): Promise<void> {\n // No cleanup necessary\n return Promise.resolve();\n }\n}","import { BasePlugin } from './BasePlugin';\nimport { GenericPluginContext } from './PluginInterface';\nimport { StructuredTool } from '@langchain/core/tools';\n\n/**\n * Base class for platform-agnostic plugins that can be used across different implementations\n */\nexport abstract class GenericPlugin extends BasePlugin<GenericPluginContext> {\n /**\n * Namespace for the plugin, used for organizing and categorizing plugins\n */\n abstract namespace: string;\n\n /**\n * Get the tools provided by this plugin\n * @returns Array of tools provided by this plugin\n */\n abstract override getTools(): StructuredTool[];\n}","import { BasePlugin } from './BasePlugin';\nimport { PluginContext } from './PluginInterface';\nimport { StructuredTool } from '@langchain/core/tools';\n\n/**\n * Base class for plugins that require HCS10 specific functionality\n */\nexport abstract class HCS10Plugin extends BasePlugin<PluginContext> {\n /**\n * Get the tools provided by this plugin\n * @returns Array of tools provided by this plugin\n */\n abstract override getTools(): StructuredTool[];\n}","import { GenericPlugin } from '../GenericPlugin';\nimport { GenericPluginContext } from '../PluginInterface';\nimport { StructuredTool } from '@langchain/core/tools';\nimport { HCS10Client } from '../../hcs10/HCS10Client';\nimport { IStateManager } from '../../state/state-types';\nimport { OpenConvaiState } from '../../state/open-convai-state';\n\nimport { RegisterAgentTool } from '../../tools/RegisterAgentTool';\nimport { SendMessageTool } from '../../tools/SendMessageTool';\nimport { ConnectionTool } from '../../tools/ConnectionTool';\nimport { FindRegistrationsTool } from '../../tools/FindRegistrationsTool';\nimport { InitiateConnectionTool } from '../../tools/InitiateConnectionTool';\nimport { ListConnectionsTool } from '../../tools/ListConnectionsTool';\nimport { SendMessageToConnectionTool } from '../../tools/SendMessageToConnectionTool';\nimport { CheckMessagesTool } from '../../tools/CheckMessagesTool';\nimport { ConnectionMonitorTool } from '../../tools/ConnectionMonitorTool';\nimport { ManageConnectionRequestsTool } from '../../tools/ManageConnectionRequestsTool';\nimport { AcceptConnectionRequestTool } from '../../tools/AcceptConnectionRequestTool';\nimport { RetrieveProfileTool } from '../../tools/RetrieveProfileTool';\nimport { ListUnapprovedConnectionRequestsTool } from '../../tools/ListUnapprovedConnectionRequestsTool';\n\n/**\n * OpenConvAI Plugin that provides all the tools from standards-agent-kit\n * This plugin enables full HCS-10 agent functionality including registration,\n * connection management, and messaging capabilities.\n */\nexport class OpenConvAIPlugin extends GenericPlugin {\n id = 'openconvai-standards-agent-kit';\n name = 'OpenConvAI Standards Agent Kit Plugin';\n description =\n 'Comprehensive plugin providing all HCS-10 agent tools for registration, connections, and messaging';\n version = '1.0.0';\n author = 'Hashgraph Online';\n namespace = 'openconvai';\n\n private hcs10Client?: HCS10Client;\n private stateManager?: IStateManager;\n private tools: StructuredTool[] = [];\n\n override async initialize(context: GenericPluginContext): Promise<void> {\n await super.initialize(context);\n\n if (!(context.client instanceof HCS10Client)) {\n throw new Error('OpenConvAIPlugin requires an HCS10Client instance');\n }\n\n this.hcs10Client = context.client as HCS10Client;\n\n this.stateManager =\n (context.stateManager as IStateManager) || new OpenConvaiState();\n\n this.initializeTools();\n\n this.context.logger.info(\n 'OpenConvAI Standards Agent Kit Plugin initialized successfully'\n );\n }\n\n private initializeTools(): void {\n if (!this.hcs10Client || !this.stateManager) {\n throw new Error(\n 'HCS10Client and StateManager must be initialized before creating tools'\n );\n }\n\n this.tools = [\n new RegisterAgentTool(this.hcs10Client, this.stateManager),\n new SendMessageTool(this.hcs10Client),\n new ConnectionTool({\n client: this.hcs10Client,\n stateManager: this.stateManager,\n }),\n new FindRegistrationsTool({\n hcsClient: this.hcs10Client,\n }),\n new RetrieveProfileTool(this.hcs10Client),\n new InitiateConnectionTool({\n hcsClient: this.hcs10Client,\n stateManager: this.stateManager,\n }),\n new ListConnectionsTool({\n hcsClient: this.hcs10Client,\n stateManager: this.stateManager,\n }),\n new SendMessageToConnectionTool({\n hcsClient: this.hcs10Client,\n stateManager: this.stateManager,\n }),\n new CheckMessagesTool({\n hcsClient: this.hcs10Client,\n stateManager: this.stateManager,\n }),\n new ConnectionMonitorTool({\n hcsClient: this.hcs10Client,\n stateManager: this.stateManager,\n }),\n new ManageConnectionRequestsTool({\n hcsClient: this.hcs10Client,\n stateManager: this.stateManager,\n }),\n new AcceptConnectionRequestTool({\n hcsClient: this.hcs10Client,\n stateManager: this.stateManager,\n }),\n new ListUnapprovedConnectionRequestsTool({\n stateManager: this.stateManager,\n hcsClient: this.hcs10Client,\n }),\n ];\n }\n\n getTools(): StructuredTool[] {\n return this.tools;\n }\n\n override async cleanup(): Promise<void> {\n this.tools = [];\n this.hcs10Client = undefined;\n this.stateManager = undefined;\n this.context.logger.info(\n 'OpenConvAI Standards Agent Kit Plugin cleaned up'\n );\n }\n}\n","import { PluginContext } from './PluginInterface';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { IPlugin } from './PluginInterface';\n\n/**\n * Configuration for loading a plugin\n */\nexport interface PluginLoadOptions {\n /**\n * Whether to initialize the plugin after loading\n * @default true\n */\n initialize?: boolean;\n}\n\n/**\n * Utility for loading plugins from different sources\n */\nexport class PluginLoader {\n /**\n * Load a plugin from a directory\n * @param directory Path to the directory containing the plugin\n * @param context Context to provide to the plugin during initialization\n * @param options Options for loading the plugin\n * @returns The loaded plugin instance\n */\n static async loadFromDirectory(\n directory: string,\n context: PluginContext,\n options: PluginLoadOptions = { initialize: true }\n ): Promise<IPlugin> {\n const manifestPath = path.join(directory, 'plugin.json');\n\n if (!fs.existsSync(manifestPath)) {\n throw new Error(`Plugin manifest not found at ${manifestPath}`);\n }\n\n try {\n const manifestContent = fs.readFileSync(manifestPath, 'utf8');\n const manifest = JSON.parse(manifestContent);\n\n // Validate manifest\n if (!manifest.id || !manifest.main) {\n throw new Error('Invalid plugin manifest: missing required fields (id, main)');\n }\n\n // Load the plugin module\n const mainPath = path.join(directory, manifest.main);\n if (!fs.existsSync(mainPath)) {\n throw new Error(`Plugin main file not found at ${mainPath}`);\n }\n\n // Import the plugin module\n const pluginModule = await import(mainPath);\n const PluginClass = pluginModule.default || pluginModule[manifest.id];\n\n if (!PluginClass) {\n throw new Error(`Could not find plugin class in ${mainPath}`);\n }\n\n // Create an instance of the plugin\n const plugin = new PluginClass();\n\n // Validate that it implements the IPlugin interface\n if (!this.isValidPlugin(plugin)) {\n throw new Error(`Plugin does not implement the IPlugin interface correctly`);\n }\n\n // Initialize the plugin if requested\n if (options.initialize) {\n await plugin.initialize(context);\n }\n\n return plugin;\n } catch (error) {\n throw new Error(`Failed to load plugin from directory ${directory}: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n\n /**\n * Load a plugin from an npm package\n * @param packageName Name of the npm package containing the plugin\n * @param context Context to provide to the plugin during initialization\n * @param options Options for loading the plugin\n * @returns The loaded plugin instance\n */\n static async loadFromPackage(\n packageName: string,\n context: PluginContext,\n options: PluginLoadOptions = { initialize: true }\n ): Promise<IPlugin> {\n try {\n // Resolve the package path\n const packagePath = require.resolve(packageName);\n const packageDir = path.dirname(packagePath);\n\n return this.loadFromDirectory(packageDir, context, options);\n } catch (error) {\n throw new Error(`Failed to load plugin from package ${packageName}: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n\n /**\n * Check if an object implements the IPlugin interface\n * @param obj Object to check\n * @returns true if the object implements IPlugin, false otherwise\n */\n private static isValidPlugin(obj: any): obj is IPlugin {\n return (\n obj &&\n typeof obj.id === 'string' &&\n typeof obj.name === 'string' &&\n typeof obj.description === 'string' &&\n typeof obj.version === 'string' &&\n typeof obj.author === 'string' &&\n typeof obj.initialize === 'function' &&\n typeof obj.getTools === 'function'\n );\n }\n}\n","import { IPlugin, PluginContext } from './PluginInterface';\nimport { StructuredTool } from '@langchain/core/tools';\nimport { Logger } from '@hashgraphonline/standards-sdk';\n\n/**\n * Registry for managing plugins in the Standards Agent Kit\n */\nexport class PluginRegistry {\n private plugins: Map<string, IPlugin> = new Map();\n private context: PluginContext;\n private logger: Logger;\n\n /**\n * Creates a new PluginRegistry instance\n * @param context The context to provide to plugins during initialization\n */\n constructor(context: PluginContext) {\n this.context = context;\n this.logger = context.logger;\n }\n\n /**\n * Register a plugin with the registry\n * @param plugin The plugin to register\n * @throws Error if a plugin with the same ID is already registered\n */\n async registerPlugin(plugin: IPlugin): Promise<void> {\n if (this.plugins.has(plugin.id)) {\n throw new Error(`Plugin with ID ${plugin.id} is already registered`);\n }\n\n await plugin.initialize(this.context);\n this.plugins.set(plugin.id, plugin);\n this.logger.info(`Plugin registered: ${plugin.name} (${plugin.id}) v${plugin.version}`);\n }\n\n /**\n * Get a plugin by ID\n * @param id The ID of the plugin to retrieve\n * @returns The plugin, or undefined if not found\n */\n getPlugin(id: string): IPlugin | undefined {\n return this.plugins.get(id);\n }\n\n /**\n * Get all registered plugins\n * @returns Array of all registered plugins\n */\n getAllPlugins(): IPlugin[] {\n return Array.from(this.plugins.values());\n }\n\n /**\n * Get all tools from all registered plugins\n * @returns Array of all tools provided by registered plugins\n */\n getAllTools(): StructuredTool[] {\n return this.getAllPlugins().flatMap(plugin => plugin.getTools());\n }\n\n /**\n * Unregister a plugin\n * @param id The ID of the plugin to unregister\n * @returns true if the plugin was unregistered, false if it wasn't found\n */\n async unregisterPlugin(id: string): Promise<boolean> {\n const plugin = this.plugins.get(id);\n if (!plugin) {\n return false;\n }\n\n if (plugin.cleanup) {\n try {\n await plugin.cleanup();\n } catch (error) {\n this.logger.error(`Error during plugin cleanup: ${error}`);\n }\n }\n\n const result = this.plugins.delete(id);\n if (result) {\n this.logger.info(`Plugin unregistered: ${plugin.name} (${plugin.id})`);\n }\n\n return result;\n }\n\n /**\n * Unregister all plugins\n */\n async unregisterAllPlugins(): Promise<void> {\n const pluginIds = Array.from(this.plugins.keys());\n for (const id of pluginIds) {\n await this.unregisterPlugin(id);\n }\n }\n}\n","import { HCS10Client, StandardNetworkType } from '../hcs10/HCS10Client';\nimport { RegisterAgentTool } from '../tools/RegisterAgentTool';\nimport { SendMessageTool } from '../tools/SendMessageTool';\nimport { ConnectionTool } from '../tools/ConnectionTool';\nimport { IStateManager } from '../state/state-types';\nimport { OpenConvaiState } from '../state/open-convai-state';\nimport { FindRegistrationsTool } from '../tools/FindRegistrationsTool';\nimport { InitiateConnectionTool } from '../tools/InitiateConnectionTool';\nimport { ListConnectionsTool } from '../tools/ListConnectionsTool';\nimport { SendMessageToConnectionTool } from '../tools/SendMessageToConnectionTool';\nimport { CheckMessagesTool } from '../tools/CheckMessagesTool';\nimport { ConnectionMonitorTool } from '../tools/ConnectionMonitorTool';\nimport { ManageConnectionRequestsTool } from '../tools/ManageConnectionRequestsTool';\nimport { AcceptConnectionRequestTool } from '../tools/AcceptConnectionRequestTool';\nimport { RetrieveProfileTool } from '../tools/RetrieveProfileTool';\nimport { ListUnapprovedConnectionRequestsTool } from '../tools/ListUnapprovedConnectionRequestsTool';\nimport { Logger } from '@hashgraphonline/standards-sdk';\nimport { ENV_FILE_PATH } from '../utils/state-tools';\n\nexport interface HCS10ClientConfig {\n operatorId?: string;\n operatorKey?: string;\n network?: StandardNetworkType;\n useEncryption?: boolean;\n registryUrl?: string;\n logLevel?: 'debug' | 'info' | 'warn' | 'error';\n}\n\nexport interface HCS10InitializationOptions {\n clientConfig?: HCS10ClientConfig;\n stateManager?: IStateManager;\n createAllTools?: boolean;\n monitoringClient?: boolean;\n}\n\n/**\n * Tool collection containing all available tools from the standards-agent-kit\n */\nexport interface HCS10Tools {\n registerAgentTool: RegisterAgentTool;\n findRegistrationsTool: FindRegistrationsTool;\n retrieveProfileTool: RetrieveProfileTool;\n initiateConnectionTool: InitiateConnectionTool;\n listConnectionsTool: ListConnectionsTool;\n sendMessageToConnectionTool: SendMessageToConnectionTool;\n checkMessagesTool: CheckMessagesTool;\n sendMessageTool: SendMessageTool;\n connectionTool: ConnectionTool;\n connectionMonitorTool: ConnectionMonitorTool;\n manageConnectionRequestsTool: ManageConnectionRequestsTool;\n acceptConnectionRequestTool: AcceptConnectionRequestTool;\n listUnapprovedConnectionRequestsTool: ListUnapprovedConnectionRequestsTool;\n}\n\n/**\n * Initializes the HCS10 client and returns pre-registered LangChain tools.\n *\n * @param options - Initialization options\n * @returns Object containing hcs10Client and requested tools\n */\nexport const initializeStandardsAgentKit = (\n options?: HCS10InitializationOptions\n): {\n hcs10Client: HCS10Client;\n monitoringClient?: HCS10Client;\n tools: Partial<HCS10Tools>;\n stateManager: IStateManager;\n} => {\n const config = options?.clientConfig || {};\n\n const operatorId = config.operatorId || process.env.HEDERA_OPERATOR_ID;\n const operatorPrivateKey =\n config.operatorKey || process.env.HEDERA_OPERATOR_KEY;\n\n const networkEnv = config.network || process.env.HEDERA_NETWORK || 'testnet';\n\n let network: StandardNetworkType;\n if (networkEnv === 'mainnet') {\n network = 'mainnet';\n } else if (networkEnv === 'testnet') {\n network = 'testnet';\n } else {\n console.warn(\n `Unsupported network specified: '${networkEnv}'. Defaulting to 'testnet'.`\n );\n network = 'testnet';\n }\n\n if (!operatorId || !operatorPrivateKey) {\n throw new Error(\n 'Operator ID and private key must be provided either through options or environment variables.'\n );\n }\n\n const shouldSilence = process.env.DISABLE_LOGGING === 'true';\n const logger = Logger.getInstance({\n level: config.logLevel || 'info',\n silent: shouldSilence,\n });\n\n const stateManager =\n options?.stateManager ||\n new OpenConvaiState({\n defaultEnvFilePath: ENV_FILE_PATH,\n defaultPrefix: 'TODD',\n });\n logger.info('State manager initialized');\n\n const hcs10Client = new HCS10Client(operatorId, operatorPrivateKey, network, {\n useEncryption: config.useEncryption,\n registryUrl: config.registryUrl,\n });\n logger.info(`HCS10Client initialized for ${operatorId} on ${network}`);\n\n let monitoringClient: HCS10Client | undefined;\n if (options?.monitoringClient) {\n monitoringClient = new HCS10Client(\n operatorId,\n operatorPrivateKey,\n network,\n {\n useEncryption: config.useEncryption,\n registryUrl: config.registryUrl,\n logLevel: 'error',\n }\n );\n logger.info('Monitoring client initialized');\n }\n\n const tools: Partial<HCS10Tools> = {};\n\n tools.registerAgentTool = new RegisterAgentTool(hcs10Client, stateManager);\n tools.sendMessageTool = new SendMessageTool(hcs10Client);\n tools.connectionTool = new ConnectionTool({\n client: monitoringClient || hcs10Client,\n stateManager,\n });\n\n if (options?.createAllTools) {\n tools.findRegistrationsTool = new FindRegistrationsTool({\n hcsClient: hcs10Client,\n });\n tools.retrieveProfileTool = new RetrieveProfileTool(hcs10Client);\n tools.initiateConnectionTool = new InitiateConnectionTool({\n hcsClient: hcs10Client,\n stateManager,\n });\n tools.listConnectionsTool = new ListConnectionsTool({\n hcsClient: hcs10Client,\n stateManager,\n });\n tools.sendMessageToConnectionTool = new SendMessageToConnectionTool({\n hcsClient: hcs10Client,\n stateManager,\n });\n tools.checkMessagesTool = new CheckMessagesTool({\n hcsClient: hcs10Client,\n stateManager,\n });\n tools.connectionMonitorTool = new ConnectionMonitorTool({\n hcsClient: monitoringClient || hcs10Client,\n stateManager,\n });\n tools.manageConnectionRequestsTool = new ManageConnectionRequestsTool({\n hcsClient: hcs10Client,\n stateManager,\n });\n tools.acceptConnectionRequestTool = new AcceptConnectionRequestTool({\n hcsClient: hcs10Client,\n stateManager,\n });\n tools.listUnapprovedConnectionRequestsTool =\n new ListUnapprovedConnectionRequestsTool({\n stateManager,\n hcsClient: hcs10Client,\n });\n\n logger.info('All tools initialized');\n }\n\n return {\n hcs10Client,\n monitoringClient,\n tools,\n stateManager,\n };\n};\n"],"names":["HCS10Client","constructor","operatorId","operatorPrivateKey","network","options","this","standardClient","StandardSDKClient","guardedRegistryBaseUrl","registryUrl","logLevel","useEncryption","shouldSilence","process","env","DISABLE_LOGGING","logger","Logger","level","silent","getOperatorId","operator","getClient","operatorAccountId","Error","toString","getNetwork","handleConnectionRequest","inboundTopicId","requestingAccountId","connectionRequestId","feeConfig","error","message","String","getAgentProfile","accountId","retrieveProfile","submitConnectionRequest","memo","waitForConnectionConfirmation","outboundTopicId","maxAttempts","delayMs","createAndRegisterAgent","metadata","builder","AgentBuilder","setName","name","setBio","description","setCapabilities","capabilities","StandardAIAgentCapability","TEXT_GENERATION","setType","type","setModel","model","setNetwork","setInboundTopicType","StandardInboundTopicType","PUBLIC","FEE_BASED","setFeeConfig","pfpBuffer","pfpFileName","byteLength","warn","info","setProfilePicture","social","Object","entries","forEach","platform","handle","addSocial","properties","key","value","addProperty","hasFees","Boolean","result","initialBalance","agentChannels","sendMessage","topicId","data","submitKey","messageResponse","topicSequenceNumber","toNumber","getMessages","mappedMessages","messages","map","sdkMessage","timestamp","created","getTime","sequence_number","sort","a","b","getMessageStream","getMessageContent","inscriptionIdOrData","getInboundTopicId","profileResponse","success","topicInfo","inboundTopic","detailedMessage","includes","getAccountAndSigner","signer","getOutboundTopicId","profile","outboundTopic","setClient","privateKey","validateOperator","isValid","initializeWithValidation","validationResult","stateManager","initializeConnectionsManager","RegisterAgentTool","StructuredTool","client","super","schema","z","object","string","describe","optional","enum","array","number","profilePicture","union","url","filename","path","feeCollectorAccountId","hbarFee","tokenFee","amount","tokenId","hbarFees","collectorAccount","tokenFees","exemptAccountIds","setAsCurrent","boolean","persistence","prefix","loadProfilePicture","getInstance","startsWith","response","axios","get","responseType","buffer","globalThis","Buffer","from","urlPathname","URL","pathname","basename","fs","existsSync","readFileSync","_call","input","AIAgentCapability","profilePictureSource","profilePictureData","hasHbarFee","hasTokenFee","hasValidTokenFee","hasHbarFees","length","hasTokenFees","collectorId","feeConfigBuilder","FeeConfigBuilder","filter","id","updatedFeeConfig","addHbarFee","fee","feeCollector","addTokenFee","processRegistrationResult","trim","newAgentAccountId","profileTopicId","pfpTopicId","validateRegistrationResult","agent","setCurrentAgent","persistAgentData","persistenceOptions","ensureAgentHasFunds","feeDescription","createFeeDescription","feeMessage","registrationDetails","source","JSON","stringify","agentName","async","baseClient","hbarBalance","requestAccount","balance","mirrorNode","HederaMirrorNode","hbarPrice","getHBARPrice","Date","balanceInUsd","toFixed","funder","targetHbar","amountToTransferHbar","Math","max","transferTx","TransferTransaction","addHbarTransfer","Hbar","fromTinybars","round","fundTxResponse","execute","getReceipt","fundingError","ensureAgentHasEnoughHbar","module","missingFields","join","tokenFeeText","SendMessageTool","lastProcessedTimestamp","disableMonitoring","monitorResponses","sequenceNumber","attempts","content","parsedContent","parse","Promise","resolve","setTimeout","ConnectionTool","rest","isMonitoring","monitoringTopic","errorMsg","monitorIncomingRequests","catch","lastProcessedMessageSequence","processedRequestIds","Set","allMessages","connectionRequests","msg","op","some","m","connection_id","debug","senderOperatorId","operator_id","split","has","confirmation","add","connectionTopicId","newConnection","targetAccountId","targetAgentName","targetInboundTopicId","addActiveConnection","handleError","stopMonitoring","SendMessageToConnectionTool","hcsClient","targetIdentifier","default","currentAgent","getCurrentAgent","connection","getConnectionByIdentifier","replyBack","InitiateConnectionTool","targetProfile","requestResult","sequenceNumberLong","isNaN","conversionError","confirmationTimeoutMs","ceil","confirmationResult","connections","listConnections","addedEntry","find","c","localConnectionId","indexOf","ListConnectionsTool","includeDetails","showPending","args","getEnhancedConnections","activeConnections","status","pendingConnections","isPending","needsConfirmation","output","conn","index","formatConnection","profileInfo","display_name","bio","substring","toLocaleString","lastActivity","connectionManager","getConnectionsManager","fetchConnectionData","updateOrAddConnection","console","CheckMessagesTool","fetchLatest","lastMessagesCount","int","positive","getLastTimestamp","messagesToProcess","latestTimestampNanos","isFetchingLatest","count","slice","reduce","maxTs","outputString","displayContent","parsed","p","parseError","updateTimestamp","FindRegistrationsTool","tags","nativeEnum","findRegistrations","registrations","reg","alias","createdAt","ConnectionMonitorTool","acceptAll","monitorDurationSeconds","defaultCollectorAccount","listConnectionsTool","updateClient","newClient","createFeeConfig","endTime","now","pollIntervalMs","lastSequenceNumber","connectionRequestsFound","acceptedConnections","skippedRequests","invoke","currentConnections","connectionsByAccountAndRequest","Map","set","newMessages","request","requestId","connectionsManager","isConnectionRequestProcessed","requestorAccountId","extractAccountId","markConnectionRequestProcessed","existingAccountConnections","acceptConnectionRequest","formatFeeString","agentAccountId","defaultCollector","defaultCollectorAccountId","exemptIds","push","collector","extractAccountFromOperatorId","profileError","feeString","hbarFeeDetails","tokenFeeDetails","update","ManageConnectionRequestsTool","action","requestKey","lastRefreshTime","refreshIntervalMs","refreshRequestsIfNeeded","listRequests","viewRequest","rejectRequest","refreshRequests","allRequests","getPendingRequests","getConnectionsNeedingConfirmation","log","requestType","requestIdDisplay","uniqueRequestKey","inboundRequestId","r","uniqueKey","originTopicId","AcceptConnectionRequestTool","numericRequestId","finalExemptions","feeConfigError","targetInboundTopic","targetProfileData","e","RetrieveProfileTool","disableCache","errorMessage","ListUnapprovedConnectionRequestsTool","sortBy","limit","pendingRequests","findAllPendingRequests","formatRequestsList","requests","sortedRequests","sortRequests","limitedRequests","statusIndicator","requestsCopy","localeCompare","ENV_FILE_PATH","cwd","OpenConvaiState","connectionMessageTimestamps","defaultEnvFilePath","defaultPrefix","disableLogging","ConnectionsManager","clearAll","sdkConnection","convertConnectionStatus","processed","initializeTimestampIfNeeded","getAllConnections","convertToActiveConnection","identifier","numericIndex","parseInt","byTopicId","getConnectionByTopicId","byAccountId","getConnectionByAccountId","timestampNanos","convertToStateStatus","envFilePath","updates","variables","envContent","updatedLines","lineIndex","findIndex","line","writeFileSync","updateEnvFile","BasePlugin","initialize","context","cleanup","ExchangeRateResponseSchema","current_rate","cent_equivalent","hbar_equivalent","expiration_time","next_rate","GetHbarPriceTool","arguments","parsedData","safeParse","isAxiosError","GenericPlugin","version","author","tools","getTools","namespace","hcs10Client","initializeTools","loadFromDirectory","directory","manifestPath","manifestContent","manifest","main","mainPath","pluginModule","import","PluginClass","plugin","isValidPlugin","loadFromPackage","packageName","packagePath","require","packageDir","dirname","obj","plugins","registerPlugin","getPlugin","getAllPlugins","Array","values","getAllTools","flatMap","unregisterPlugin","delete","unregisterAllPlugins","pluginIds","keys","config","clientConfig","HEDERA_OPERATOR_ID","operatorKey","HEDERA_OPERATOR_KEY","networkEnv","HEDERA_NETWORK","monitoringClient","registerAgentTool","sendMessageTool","connectionTool","createAllTools","findRegistrationsTool","retrieveProfileTool","initiateConnectionTool","sendMessageToConnectionTool","checkMessagesTool","connectionMonitorTool","manageConnectionRequestsTool","acceptConnectionRequestTool","listUnapprovedConnectionRequestsTool"],"mappings":"siBAqDO,MAAMA,EAOX,WAAAC,CACEC,EACAC,EACAC,EACAC,GAMKC,KAAAC,eAAiB,IAAIC,cAAkB,CAC1CJ,UACAF,aACAC,qBACAM,uBAAwBJ,GAASK,YACjCC,SAAUN,GAASM,WAEhBL,KAAAG,uBAAyBJ,GAASK,aAAe,GACjDJ,KAAAM,cAAgBP,GAASO,gBAAiB,EACzC,MAAAC,EAAgD,SAAhCC,QAAQC,IAAIC,gBAC7BV,KAAAW,OAAS,IAAIC,SAAO,CACvBC,MAAOd,GAASM,UAAY,OAC5BS,OAAQP,GACT,CAGI,aAAAQ,GACL,MAAMC,EAAWhB,KAAKC,eAAegB,YAAYC,kBACjD,IAAKF,EACG,MAAA,IAAIG,MAAM,0DAElB,OAAOH,EAASI,UAAS,CAGpB,UAAAC,GACE,OAAArB,KAAKC,eAAeoB,YAAW,CAGxC,6BAAaC,CACXC,EACAC,EACAC,EACAC,GAEI,IAOK,aANc1B,KAAKC,eAAeqB,wBACvCC,EACAC,EACAC,EACAC,SAGKC,GAKP,MAJA3B,KAAKW,OAAOgB,MACV,sCAAsCF,eAAiCF,KACvEI,GAEI,IAAIR,MACR,wCACEQ,aAAiBR,MAAQQ,EAAMC,QAAUC,OAAOF,KAEpD,CACF,CAMF,qBAAaG,CAAgBC,GACpB,OAAA/B,KAAKC,eAAe+B,gBAAgBD,EAAS,CAMtD,6BAAaE,CACXV,EACAW,GAEA,OAAOlC,KAAKC,eAAegC,wBACzBV,EACAW,EACF,CAMF,mCAAaC,CACXC,EACAX,EACAY,EAAc,GACdC,EAAU,KAEV,OAAOtC,KAAKC,eAAekC,8BACzBC,EACAX,EACAY,EACAC,EACF,CAgBF,4BAAaC,CACXC,GAEA,MAAMC,GAAU,IAAIC,gBACjBC,QAAQH,EAASI,MACjBC,OAAOL,EAASM,aAAe,IAC/BC,gBACCP,EAASQ,aACLR,EAASQ,aACT,CAACC,oBAA0BC,kBAEhCC,QAASX,EAASY,MAAQ,cAC1BC,SAASb,EAASc,OAAS,oBAC3BC,WAAWvD,KAAKqB,cAChBmC,oBAAoBC,mBAAyBC,QAE5ClB,GAAUd,YACJe,EAAAe,oBAAoBC,mBAAyBE,WAC7ClB,EAAAmB,aAAapB,EAASd,YAG5Bc,EAASqB,WAAarB,EAASsB,YACK,IAAlCtB,EAASqB,UAAUE,WACrB/D,KAAKW,OAAOqD,KACV,4DAGFhE,KAAKW,OAAOsD,KACV,4BAA4BzB,EAASsB,gBAAgBtB,EAASqB,UAAUE,qBAE1EtB,EAAQyB,kBAAkB1B,EAASqB,UAAWrB,EAASsB,cAGzD9D,KAAKW,OAAOqD,KACV,kHAIAxB,EAAS2B,QACJC,OAAAC,QAAQ7B,EAAS2B,QAAQG,SAAQ,EAAEC,EAAUC,MAC1C/B,EAAAgC,UAAUF,EAA4BC,MAI9ChC,EAASkC,YACJN,OAAAC,QAAQ7B,EAASkC,YAAYJ,SAAQ,EAAEK,EAAKC,MACzCnC,EAAAoC,YAAYF,EAAKC,MAIzB,IACI,MAAAE,EAAUC,QAAQvC,GAAUd,WAC5BsD,QAAehF,KAAKC,eAAesC,uBAAuBE,EAAS,CACvEwC,eAAgBH,EAAU,QAAK,IAW1B,OARLE,GAAQxC,UAAUjB,gBAClByD,GAAQxC,UAAUJ,kBAElBpC,KAAKkF,cAAgB,CACnB3D,eAAgByD,EAAOxC,SAASjB,eAChCa,gBAAiB4C,EAAOxC,SAASJ,kBAG9B4C,QACArD,GAEP,MADK3B,KAAAW,OAAOgB,MAAM,4CAA6CA,GACzD,IAAIR,MACR,oCACEQ,aAAiBR,MAAQQ,EAAMC,QAAUC,OAAOF,KAEpD,CACF,CAcF,iBAAawD,CACXC,EACAC,EACAnD,EACAoD,GAEItF,KAAKM,cAIL,IACI,MAAAiF,QAAwBvF,KAAKC,eAAekF,YAChDC,EACAC,EACAnD,EACAoD,GAEK,OAAAC,EAAgBC,qBAAqBC,iBACrC9D,GAEP,MADA3B,KAAKW,OAAOgB,MAAM,kCAAkCyD,KAAYzD,GAC1D,IAAIR,MACR,2BACEQ,aAAiBR,MAAQQ,EAAMC,QAAUC,OAAOF,KAEpD,CACF,CASF,iBAAa+D,CAAYN,GAGnB,IACF,MAEMO,SAFe3F,KAAKC,eAAeyF,YAAYN,IAEvBQ,SAASC,KAAKC,IAC1C,MAAMC,EAAYD,GAAYE,SAASC,WAAa,EAE7C,MAAA,IACFH,EACHC,YACAV,KAAMS,EAAWT,KACjBa,gBAAiBJ,EAAWI,oBAOzB,OAJQP,EAAAQ,MACb,CAACC,EAA0BC,IACzBD,EAAEL,UAAYM,EAAEN,YAEb,CAAEH,SAAUD,SACZhE,GAEA,OADP3B,KAAKW,OAAOgB,MAAM,qCAAqCyD,KAAYzD,GAC5D,CAAEiE,SAAU,GAAG,CACxB,CAGF,sBAAaU,CAAiBlB,GAGrB,OAAApF,KAAKC,eAAeqG,iBAAiBlB,EAAO,CAQrD,uBAAamB,CAAkBC,GACzB,IAIK,aAHexG,KAAKC,eAAesG,kBACxCC,SAGK7E,GAKP,MAJA3B,KAAKW,OAAOgB,MACV,yCAAyC6E,IACzC7E,GAEI,IAAIR,MACR,uCACEQ,aAAiBR,MAAQQ,EAAMC,QAAUC,OAAOF,KAEpD,CACF,CASF,uBAAa8E,GACP,IACI,MAAA7G,EAAaI,KAAKe,gBACxBf,KAAKW,OAAOsD,KACV,iDAAiDrE,8BAEnD,MAAM8G,QAAwB1G,KAAK8B,gBAAgBlC,GACnD,GAAI8G,EAAgBC,SAAWD,EAAgBE,WAAWC,aAIxD,OAHA7G,KAAKW,OAAOsD,KACV,kDAAkDrE,MAAe8G,EAAgBE,UAAUC,gBAEtFH,EAAgBE,UAAUC,aAEjC,MAAM,IAAI1F,MACR,qDAAqDvB,uBAAgC8G,EAAgBC,mBAAmBD,EAAgB/E,eAGrIA,GACP3B,KAAKW,OAAOgB,MACV,6DAA6D3B,KAAKe,oBAClEY,GAEI,MAAA/B,EAAaI,KAAKe,gBACpB,IAAA+F,EAAkB,+CAA+ClH,KAW/D,MATJ+B,aAAiBR,OACjBQ,EAAMC,QAAQmF,SAAS,qCAEvBD,GAAmB,0FAA0FlH,oIACpG+B,aAAiBR,MACP2F,GAAA,YAAYnF,EAAMC,UAElBkF,GAAA,sBAAsBjF,OAAOF,KAE5C,IAAIR,MAAM2F,EAAe,CACjC,CAOK,mBAAAE,GACC,MAAAhC,EAAShF,KAAKC,eAAe+G,sBAC5B,MAAA,CACLjF,UAAWiD,EAAOjD,UAClBkF,OAAQjC,EAAOiC,OACjB,CASF,wBAAaC,GACL,MAAAtH,EAAaI,KAAKe,gBAClBoG,QAAgBnH,KAAK8B,gBAAgBlC,GAC3C,GAAIuH,EAAQR,SAAWQ,EAAQP,WAAWQ,cACxC,OAAOD,EAAQP,UAAUQ,cAEzB,MAAM,IAAIjG,MACR,sDAAsDvB,uBAAgCuH,EAAQR,mBAAmBQ,EAAQxF,QAE7H,CAGK,SAAA0F,CAAUtF,EAAmBuF,GAOlC,OANKtH,KAAAC,eAAiB,IAAIC,cAAkB,CAC1CJ,QAASE,KAAKqB,aACdzB,WAAYmC,EACZlC,mBAAoByH,EACpBnH,uBAAwBH,KAAKG,yBAExBH,KAAKC,cAAA,CAMd,sBAAcsH,CAAiBxH,GAKzB,IAEFC,KAAKqH,UAAUtH,EAAQgC,UAAWhC,EAAQuH,YAMnC,MAAA,CACLE,SAAS,EACTxG,SAAU,CAAEe,UALK/B,KAAKe,wBAOjBY,GAEA,OADP3B,KAAKW,OAAOgB,MAAM,qBAAqBA,KAChC,CACL6F,SAAS,EACT7F,MAAOA,aAAiBR,MAAQQ,EAAMC,QAAUC,OAAOF,GACzD,CACF,CAGF,8BAAM8F,CAAyB1H,GAK7B,MAAM2H,QAAyB1H,KAAKuH,iBAAiBxH,GAS9C,OAPH2H,EAAiBF,SAEfzH,EAAQ4H,cACF5H,EAAA4H,aAAaC,6BAA6B5H,KAAKC,gBAIpDyH,CAAA,ECxZJ,MAAMG,UAA0BC,EAAAA,eAkHrC,WAAAnI,CAAYoI,EAAqBJ,GACzBK,QAlHDhI,KAAA4C,KAAA,iBAEL5C,KAAA8C,YAAA,kPAIF9C,KAAAiI,OAASC,IAAEC,OAAO,CAChBvF,KAAMsF,EAAAA,EAAEE,SAASC,SAAS,qCAC1BvF,YAAaoF,EACVA,EAAAE,SACAE,WACAD,SAAS,qCACZjF,KAAM8E,EAAAA,EACHK,KAAK,CAAC,aAAc,WACpBD,WACAD,SAAS,6CACZ/E,MAAO4E,EACJA,EAAAE,SACAE,WACAD,SAAS,2CACZrF,aAAckF,IACXM,MAAMN,EAAAA,EAAEO,UACRH,WACAD,SACC,iHAEJK,eAAgBR,IACbS,MAAM,CACLT,EAAAA,EAAEE,SAASC,SAAS,iDACpBH,EAAAA,EAAEC,OAAO,CACPS,IAAKV,EAAAA,EAAEE,SAASC,SAAS,wBACzBQ,SAAUX,EAAAA,EAAEE,SAASC,SAAS,mCAEhCH,EAAAA,EAAEC,OAAO,CACPW,KAAMZ,EAAAA,EAAEE,SAASC,SAAS,8BAC1BQ,SAAUX,EAAEA,EAAAE,SAASE,WAAWD,SAAS,gCAG5CC,WACAD,SACC,mEAEJU,sBAAuBb,EAAAA,EACpBE,SACAE,WACAD,SACC,gIAEJW,QAASd,EAAAA,EACNO,SACAH,WACAD,SACC,qJAEJY,SAAUf,IACPC,OAAO,CACNe,OAAQhB,IAAEO,SACVU,QAASjB,IAAEE,WAEZE,WACAD,SACC,2LAEJe,SAAUlB,EACPA,EAAAM,MACCN,EAAAA,EAAEC,OAAO,CACPe,OAAQhB,IAAEO,SACVY,iBAAkBnB,EAAAA,EAAEE,SAASE,cAGhCA,WACAD,SACC,oHAEJiB,UAAWpB,EACRA,EAAAM,MACCN,EAAAA,EAAEC,OAAO,CACPe,OAAQhB,IAAEO,SACVU,QAASjB,IAAEE,SACXiB,iBAAkBnB,EAAAA,EAAEE,SAASE,cAGhCA,WACAD,SACC,qHAEJkB,iBAAkBrB,IACfM,MAAMN,EAAAA,EAAEE,UACRE,WACAD,SACC,8EAEJmB,aAActB,EAAAA,EACXuB,UACAnB,WACAD,SACC,uHAEJqB,YAAaxB,IACVC,OAAO,CACNwB,OAAQzB,EAAAA,EAAEE,SAASE,aAEpBA,WACAD,SACC,wMAWJrI,KAAK+H,OAASA,EACd/H,KAAK2H,aAAeA,CAAA,CAQtB,wBAAciC,CACZlB,GAEM,MAAA/H,EAASC,SAAOiJ,YAAY,CAChChJ,MAAO,UAGL,IACF,IAAK6H,EACI,OAAA,KAGL,GAA0B,iBAAnBA,EAA6B,CAKtC,GAHEA,EAAeoB,WAAW,YAC1BpB,EAAeoB,WAAW,YAEjB,CACFnJ,EAAAsD,KAAK,qCAAqCyE,KACjD,MAAMqB,QAAiBC,EAAMC,IAAIvB,EAAgB,CAC/CwB,aAAc,gBAEVC,EAASC,WAAAC,OAAOC,KAAKP,EAAS1E,MAE9BkF,EAAc,IAAIC,IAAI9B,GAAgB+B,SAGrC,MAAA,CAAEN,SAAQtB,SAFAC,EAAK4B,SAASH,IAAgB,cAErB,CACrB,CACL,IAAKI,EAAGC,WAAWlC,GAEV,OADA/H,EAAAqD,KAAK,mCAAmC0E,KACxC,KAGF/H,EAAAsD,KAAK,sCAAsCyE,KAC5C,MAAAyB,EAASQ,EAAGE,aAAanC,GAGxB,MAAA,CAAEyB,SAAQtB,SAFAC,EAAK4B,SAAShC,GAEL,CAC5B,CAGF,GAAI,QAASA,EAAgB,CAC3B/H,EAAOsD,KAAK,qCAAqCyE,EAAeE,OAChE,MAAMmB,QAAiBC,EAAMC,IAAIvB,EAAeE,IAAK,CACnDsB,aAAc,gBAEVC,EAASC,WAAAC,OAAOC,KAAKP,EAAS1E,MAG7B,MAAA,CAAE8E,SAAQtB,SAFAH,EAAeG,UAAY,cAElB,CAG5B,GAAI,SAAUH,EAAgB,CAC5B,IAAKiC,EAAGC,WAAWlC,EAAeI,MAEzB,OADPnI,EAAOqD,KAAK,mCAAmC0E,EAAeI,QACvD,KAGFnI,EAAAsD,KACL,sCAAsCyE,EAAeI,QAEvD,MAAMqB,EAASQ,EAAGE,aAAanC,EAAeI,MAIvC,MAAA,CAAEqB,SAAQtB,SAFfH,EAAeG,UAAYC,EAAK4B,SAAShC,EAAeI,MAEhC,CAGrB,OAAA,WACAnH,GAEA,OADAhB,EAAAgB,MAAM,kCAAmCA,GACzC,IAAA,CACT,CAOF,WAAMmJ,CAAMC,GACJ,MAAApK,EAASC,SAAOiJ,YAAY,CAChChJ,MAAO,UAGH2B,EAAkC,CACtCI,KAAMmI,EAAMnI,KACZE,YAAaiI,EAAMjI,YACnBM,KAAM2H,EAAM3H,KACZE,MAAOyH,EAAMzH,MACbN,aAAc+H,EAAM/H,cAAgB,CAACgI,EAAAA,kBAAkB9H,iBACvDwB,WAAY,CAAA,GAGd,IAAIuG,EAAuB,GAC3B,GAAIF,EAAMrC,eAAgB,CAClB,MAAAwC,QAA2BlL,KAAK4J,mBACpCmB,EAAMrC,gBAER,GAAIwC,EAAoB,CAChB,MAAAf,OAAEA,EAAQtB,SAAAA,GAAaqC,EAC7B1I,EAASqB,UAAYsG,EACrB3H,EAASsB,YAAc+E,EAEa,iBAAzBkC,EAAMrC,eACfuC,EAAuBF,EAAMrC,eACpB,QAASqC,EAAMrC,eACxBuC,EAAuBF,EAAMrC,eAAeE,IACnC,SAAUmC,EAAMrC,iBACzBuC,EAAuBF,EAAMrC,eAAeI,KAC9C,CACF,CAGF,MAAMqC,OAA+B,IAAlBJ,EAAM/B,SAAyB+B,EAAM/B,QAAU,EAC5DoC,EAAcpL,KAAKqL,iBAAiBN,EAAM9B,UAC1CqC,EAAcP,EAAM3B,UAAY2B,EAAM3B,SAASmC,OAAS,EACxDC,EAAeT,EAAMzB,WAAayB,EAAMzB,UAAUiC,OAAS,EAE7D,GAAAJ,GAAcC,GAAeE,GAAeE,EAAc,CAC5D,MAAQzJ,UAAWb,GACjBlB,KAAK+H,OAAOf,sBACRyE,EAAcV,EAAMhC,uBAAyB7H,EAEnD,IAAKuK,EACI,MAAA,gGAGH,MAAAC,EAAmB,IAAIC,mBAAiB,CAC5C7L,QAASE,KAAK+H,OAAO1G,aACrBV,WAGE,IACI,MAAA4I,EACJwB,EAAMxB,kBAAkBqC,QACrBC,GAAOA,IAAOJ,GAAeI,EAAG/B,WAAW,UACzC,GAEP,IAAIgC,EAAmBJ,EAavB,GAXIP,IACKxK,EAAAsD,KACL,oBAAoB8G,EAAM/B,mCAAmCyC,KAE/DK,EAAmBA,EAAiBC,WAClChB,EAAM/B,QACNyC,EACAlC,IAIA+B,EACS,IAAA,MAAAU,KAAOjB,EAAM3B,SAAW,CAC3B,MAAA6C,EAAeD,EAAI3C,kBAAoBoC,EACtC9K,EAAAsD,KACL,oBAAoB+H,EAAI9C,kCAAkC+C,KAE5DH,EAAmBA,EAAiBC,WAClCC,EAAI9C,OACJ+C,EACA1C,EACF,CAmBJ,GAfI6B,IACKzK,EAAAsD,KACL,qBAAqB8G,EAAM9B,SAAUC,mBACnC6B,EAAM9B,SAAUE,8BACKsC,KAEzBK,QAAyBA,EAAiBI,YACxCnB,EAAM9B,SAAUC,OAChB6B,EAAM9B,SAAUE,QAChBsC,OACA,EACAlC,IAIAiC,EACS,IAAA,MAAAQ,KAAOjB,EAAMzB,UAAY,CAC5B,MAAA2C,EAAeD,EAAI3C,kBAAoBoC,EACtC9K,EAAAsD,KACL,qBAAqB+H,EAAI9C,mBAAmB8C,EAAI7C,8BAA8B8C,KAEhFH,QAAyBA,EAAiBI,YACxCF,EAAI9C,OACJ8C,EAAI7C,QACJ8C,OACA,EACA1C,EACF,CAIJ/G,EAASd,UAAYoK,EACrBnL,EAAOsD,KAAK,+CACLtC,GACP,MAAO,4CACLA,aAAiBR,MAAQQ,EAAMC,QAAUC,OAAOF,IAClD,CACF,CAGE,IACFhB,EAAOsD,KAAK,mCAEN,MAAAe,QAAgBhF,KAAK+H,OAAOxF,uBAChCC,GAGF,OAAOxC,KAAKmM,0BACVnH,EACA+F,EACAE,SAEKtJ,GACA,MAAA,2CAA2CoJ,EAAMnI,kBACtDjB,aAAiBR,MAAQQ,EAAMC,QAAUC,OAAOF,IAClD,CACF,CAMM,gBAAA0J,CAAiBpC,GAIhB,SACLA,GACAA,EAASC,OAAS,GAClBD,EAASE,SACmB,KAA5BF,EAASE,QAAQiD,OAAW,CAOhC,+BAAcD,CACZnH,EACA+F,EACAE,EAA+B,IAEzB,MAAAoB,EAAoBrH,GAAQxC,UAAUT,WAAa,GACnDR,EAAiByD,GAAQxC,UAAUjB,gBAAkB,GACrDa,EAAkB4C,GAAQxC,UAAUJ,iBAAmB,GACvDkK,EAAiBtH,GAAQxC,UAAU8J,gBAAkB,GACrDhF,EAAatC,GAAQxC,UAAU8E,YAAc,GAC7CiF,EAAavH,GAAQxC,UAAU+J,WAUnC,GARGvM,KAAAwM,2BACHH,EACA9K,EACAa,EACAkF,GAIAtH,KAAK2H,cACLL,GACA+E,GACA9K,GACAa,SACwB,IAAvB2I,EAAMvB,cAA8BuB,EAAMvB,cAC3C,CACA,MAAMiD,EAAQ,CACZ7J,KAAMmI,EAAMnI,KACZb,UAAWsK,EACX9K,iBACAa,kBACAkK,iBACAhF,aACAiF,cAKF,GAFKvM,KAAA2H,aAAa+E,gBAAgBD,GAE9BzM,KAAK2H,aAAagF,kBAAoB5B,EAAMrB,YAC1C,IACF,MAAMkD,EAA8C,CAClDxJ,KAAM,WACNuG,OAAQoB,EAAMrB,YAAYC,cAGtB3J,KAAK2H,aAAagF,iBAAiBF,EAAOG,SACzCjL,GACPf,EAAAA,OAAOiJ,cAAc7F,KAAK,+BAAgCrC,EAAK,CAEnE,OAGI3B,KAAK6M,oBAAoBR,EAAmBtB,EAAMnI,MAElD,MAAAkK,EAAiB9M,KAAK+M,qBAAqBhC,GAC3CiC,EAAaF,EACf,SAASA,yBACT,GAEEG,EAAgD,CACpDtG,SAAS,EACT/E,QAAS,kCAAkCmJ,EAAMnI,QAAQoK,KACzDpK,KAAMmI,EAAMnI,KACZb,UAAWsK,EACX/E,aACA/F,iBACAa,kBACAkK,eAAgBA,GAAkB,MAClCtJ,aAAc+H,EAAM/H,cAAgB,CAACgI,EAAAA,kBAAkB9H,iBACvD4B,WAAYiG,EAAM/B,UAAWhJ,KAAKqL,iBAAiBN,EAAM9B,WACzDD,QAAS+B,EAAM/B,SAAW,EAC1BC,SAAU8B,EAAM9B,UAAY,MAUvB,OAPHsD,GAActB,KAChBgC,EAAoBvE,eAAiB,CACnCwE,OAAQjC,EACR7F,QAASmH,IAINY,KAAKC,UAAUH,EAAmB,CAM3C,yBAAcJ,CACZ9K,EACAsL,GAEI,UC5gBRC,eACE3M,EACA4M,EACAxL,EACAsL,GAEI,IACF,MAEMG,SAFgBD,EAAWE,eAAe1L,IACxB2L,QAAQA,QACF,IAE9B/M,EAAOsD,KAAK,GAAGoJ,aAAqBtL,SAAiByL,UAEjD,IACF,MAAMG,EAAa,IAAIC,mBAAiB,UAAWjN,GAC7CkN,QAAkBF,EAAWG,aAAa,IAAIC,MAEpD,GAAIF,EAAW,CACb,MAAMG,EAAeR,EAAcK,EAGnC,GAFOlN,EAAAsD,KAAK,GAAGoJ,sBAA8BW,EAAaC,QAAQ,MAE9DD,EAxBoB,EAwBa,CAC5BrN,EAAAqD,KACL,GAAGqJ,aAAqBtL,uBAAiDiM,EAAaC,QACpF,4BAIA,IACI,MAAAC,EAASX,EAAWvG,sBACpBmH,EAhCmB,GAgCkBN,EACrCO,EAAuBC,KAAKC,IAAI,EAAGH,EAAaX,GAEtD,GAAIY,EAAuB,EAAG,CACtB,MAAAG,GAAa,IAAIC,EAAAA,qBACpBC,gBACCP,EAAOnM,UACP2M,EAAAA,KAAKC,aACHN,KAAKO,OAAyC,IAAnCR,KAGdK,gBACC1M,EACA2M,EAAAA,KAAKC,aACHN,KAAKO,MAA6B,IAAvBR,KAIVzN,EAAAsD,KACL,WAAWoJ,aAAqBtL,UAAkBqM,EAAqBH,QACrE,gBACaC,EAAOnM,aAGlB,MAAA8M,QAAuBN,EAAWO,QACtCvB,EAAWtM,mBAEP4N,EAAeE,WAAWxB,EAAWtM,aACpCN,EAAAsD,KACL,uBAAuBoJ,aAAqBtL,KAC9C,MAEOpB,EAAAsD,KACL,GAAGoJ,aAAqBtL,gDAGrBiN,GACArO,EAAAgB,MACL,gCAAgC0L,aAAqBtL,KACrDiN,GAEKrO,EAAAqD,KACL,2BAA2BjC,6BA1EJ,GA2EG8L,GACxBI,QAAQ,WACZ,CACF,CACF,MAEOtN,EAAAqD,KACL,+FAGGrC,GACAhB,EAAAqD,KACL,0EACF,QAEKrC,GACPhB,EAAOgB,MAAM,mBAAmB0L,qBAA8B1L,EAAK,CAEvE,CDkbYsN,CACJrO,EAAAA,OAAOiJ,YAAY,CACjBqF,OAAQ,sBAEVlP,KAAK+H,OAAO9H,eACZ8B,EACAsL,SAEK1L,GACPf,EAAAA,OAAOiJ,cAAclI,MAAM,4BAA6BA,EAAK,CAC/D,CAMM,0BAAA6K,CACNzK,EACAR,EACAa,EACAkF,GAEA,KAAKvF,GAAcR,GAAmBa,GAAoBkF,GAAY,CACpE,MAAM6H,EAAgB,EACnBpN,GAAa,aACbR,GAAkB,kBAClBa,GAAmB,mBACnBkF,GAAc,cAEdsE,OAAO7G,SACPqK,KAAK,MACR,MAAM,IAAIjO,MACR,6EAA6EgO,MAC/E,CACF,CAMM,oBAAApC,CAAqBhC,GAC3B,MAAMI,EAAaJ,EAAM/B,SAAW+B,EAAM/B,QAAU,EAC9CoC,EAAcpL,KAAKqL,iBAAiBN,EAAM9B,UAC5C,IAACkC,IAAeC,EACX,MAAA,GAGT,IAAItI,EAAc,GAId,GAHAqI,IACarI,GAAA,GAAGiI,EAAM/B,gBAEtBoC,GAAeL,EAAM9B,SAAU,CAC3B,MAAAoG,EAAe,GAAGtE,EAAM9B,SAASC,mBAAmB6B,EAAM9B,SAASE,UAC1DrG,GAAAA,EAAc,QAAQuM,IAAiBA,CAAA,CAEjD,OAAAvM,CAAA,EElkBJ,MAAMwM,UAAwBxH,EAAAA,eAoBnC,WAAAnI,CAAYoI,GACJC,QApBDhI,KAAA4C,KAAA,eAEL5C,KAAA8C,YAAA,uFAEF9C,KAAQuP,uBAAiC,EAGzCvP,KAAAiI,OAASC,IAAEC,OAAO,CAChB/C,QAAS8C,EAAAA,EAAEE,SAASC,SAAS,8CAC7BzG,QAASsG,EAAAA,EAAEE,SAASC,SAAS,+BAC7BmH,kBAAmBtH,EAChBA,EAAAuB,UACAnB,WACAD,SAAS,iDAQZrI,KAAK+H,OAASA,EACd/H,KAAKW,OAASC,EAAOA,OAAAiJ,YAAY,CAAEqF,OAAQ,mBAAmB,CAMhE,WAAMpE,CAAMC,GAKN,IACI,MAAA/F,QAAehF,KAAK+H,OAAO5C,YAC/B4F,EAAM3F,QACN2F,EAAMnJ,SAER,IAAKoD,EACG,MAAA,IAAI7D,MAAM,0BAGd,GADJnB,KAAKW,OAAOsD,KAAK,qCAAqCe,KACjD+F,EAAMyE,kBAMF,MAAA,sCAAsCzE,EAAM3F,UANvB,CAC5B,MAAM2E,QAAiB/J,KAAKyP,iBAAiB1E,EAAM3F,QAASJ,GAC5D,MAAO,sCAAsC+F,EAAM3F,UACjD2E,EAAW,eAAeA,IAAa,IACzC,QAIKpI,GACP,MAAM,IAAIR,MACR,2BACEQ,aAAiBR,MAAQQ,EAAMC,QAAUC,OAAOF,KAEpD,CACF,CAGF,sBAAc8N,CACZrK,EACAsK,GAGA,IAAIC,EAAW,EAEf,KAAOA,EAHa,IAGW,CACzB,IACF,MAAM/J,QAAiB5F,KAAK+H,OAAOzB,iBAAiBlB,GAEzC,IAAA,MAAAxD,KAAWgE,EAASA,SAC7B,GACEhE,EAAQoE,SACRpE,EAAQoE,QAAQC,UAAYjG,KAAKuP,uBACjC,CACKvP,KAAAuP,uBAAyB3N,EAAQoE,QAAQC,UAE9C,MAAM2J,QAAgB5P,KAAK+H,OAAOxB,kBAAkB3E,EAAQyD,MAAQ,IAEhE,IAAAwK,EACA,IACcA,EAAA1C,KAAK2C,MAAMF,SACpBjO,GACP3B,KAAKW,OAAOgB,MAAM,kCAAkCA,KACpD,QAAA,CAEE,GAAAC,EAAQsE,gBAAkBwJ,EAE5B,OAAIG,GAA+C,iBAAvBA,EAAcxK,KACjCwK,EAAcxK,KAEhB8H,KAAKC,UAAUyC,EACxB,QAGGlO,GACP3B,KAAKW,OAAOgB,MAAM,+BAA+BA,IAAO,CAG1DgO,UACM,IAAII,SAASC,GAAYC,WAAWD,EAAS,MAAK,CAGnD,OAAA,IAAA,EC3FJ,MAAME,UAAuBpI,EAAAA,eAiBlC,WAAAnI,EAAYoI,OAAEA,EAAAJ,aAAQA,KAAiBwI,IACrCnI,MAAMmI,GAjBDnQ,KAAA4C,KAAA,sBAEL5C,KAAA8C,YAAA,uOAIF9C,KAAQoQ,cAAwB,EAChCpQ,KAAQqQ,gBAAiC,KAGhCrQ,KAAAiI,OAAAC,IAAEC,OAAO,CAAA,GAQhBnI,KAAK+H,OAASA,EACd/H,KAAK2H,aAAeA,EACf3H,KAAAW,OAASC,SAAOiJ,YAAY,CAC/BqF,OAAQ,iBACRrO,MAAO,QACR,CAOH,WAAMiK,GAEA,IAAAvJ,EACA,IAEeA,QAAMvB,KAAK+H,OAAOtB,0BAC5B9E,GACD,MAAA2O,EAAW,kDACf3O,aAAiBR,MAAQQ,EAAMC,QAAUC,OAAOF,KAG3C,OADF3B,KAAAW,OAAOgB,MAAM2O,GACXA,CAAA,CAGT,OAAK/O,EAIDvB,KAAKoQ,aACHpQ,KAAKqQ,kBAAoB9O,EACpB,4BAA4BA,KAE5B,gDAAgDvB,KAAKqQ,qDAKhErQ,KAAKoQ,cAAe,EACpBpQ,KAAKqQ,gBAAkB9O,EACvBvB,KAAKW,OAAOsD,KACV,sDAAsD1C,QAKxDvB,KAAKuQ,wBAAwBhP,GAAgBiP,OAAO7O,IAClD3B,KAAKW,OAAOgB,MACV,uBAAuBJ,wCACvBI,GAEF3B,KAAKoQ,cAAe,EACpBpQ,KAAKqQ,gBAAkB,QAGlB,oCAAoC9O,gDA7BlC,wEA6BgD,CAM3D,6BAAcgP,CAAwBhP,GACpCvB,KAAKW,OAAOsD,KAAK,4BAA4B1C,QAE7C,IAAIkP,EAA+B,EAC7B,MAAAC,MAA0BC,IAGhC,KAAO3Q,KAAKoQ,cAAgBpQ,KAAKqQ,kBAAoB9O,GAAgB,CAC/D,IACF,MAEMqP,SAFuB5Q,KAAK+H,OAAOrC,YAAYnE,IAElBqE,SAE7BiL,EAAqBD,EAAYhF,QACpCkF,GACY,uBAAXA,EAAIC,IAC2B,iBAAxBD,EAAI5K,kBAIf,IAAA,MAAWtE,KAAWiP,EAAoB,CAExCJ,EAA+BpC,KAAKC,IAClCmC,EACA7O,EAAQsE,iBAAmB,GAG7B,MAAMzE,EAAsBG,EAAQsE,gBACpC,IAAKzE,EACF,SAQH,GAJuBmP,EAAYI,MAChCC,GAAe,uBAATA,EAAEF,IAA+BE,EAAEC,gBAAkBzP,IAG1C,CAClBzB,KAAKW,OAAOwQ,MACV,uBAAuB1P,2DAEzB,QAAA,CAKI,MAAA2P,EAAmBxP,EAAQyP,aAAe,GAC1C7P,EAAsB4P,EAAiBE,MAAM,KAAK,IAAM,KAE9D,GAAK9P,EAOD,GAAAkP,EAAoBa,IAAI9P,GAC1BzB,KAAKW,OAAOsD,KACV,uBAAuBxC,sDAFvB,CAOJzB,KAAKW,OAAOsD,KACV,kCAAkCxC,kBAAoCD,QAGpE,IAEI,MAAAgQ,QAAqBxR,KAAK+H,OAAOzG,wBACrCC,EACAC,EACAC,GAGFiP,EAAoBe,IAAIhQ,GACxBzB,KAAKW,OAAOsD,KACV,qCAAqCxC,4BAA8C+P,EAAaE,qBAIlG,MAAMC,EAAkC,CACtCC,gBAAiBpQ,EACjBqQ,gBAAiB,SAASrQ,IAC1BsQ,qBAAsB,MACtBJ,kBAAmBF,EAAaE,mBAE7B1R,KAAA2H,aAAaoK,oBAAoBJ,GACtC3R,KAAKW,OAAOsD,KACV,kCAAkCzC,kBAE7BwQ,GACPhS,KAAKW,OAAOgB,MACV,sCAAsCF,UAA4BD,KAClEwQ,EACF,CAnCA,MAVAhS,KAAKW,OAAOqD,KACV,+DAA+DoN,mBAAkC3P,eA6CrG,QAEKE,GACP3B,KAAKW,OAAOgB,MACV,mDAAmDJ,KACnDI,EACF,OAKI,IAAIoO,SAASC,GAAYC,WAAWD,EAAS,MAAK,CAG1DhQ,KAAKW,OAAOsD,KAAK,qCAAqC1C,MACtDvB,KAAKoQ,cAAe,EACpBpQ,KAAKqQ,gBAAkB,IAAA,CAIlB,cAAA4B,GACDjS,KAAKoQ,cACPpQ,KAAKW,OAAOsD,KACV,iCAAiCjE,KAAKqQ,sBAExCrQ,KAAKoQ,cAAe,EACpBpQ,KAAKqQ,gBAAkB,MAElBrQ,KAAAW,OAAOsD,KAAK,oCACnB,ECpNG,MAAMiO,UAAoCpK,EAAAA,eAkB/C,WAAAnI,EAAYwS,UACVA,EAAAxK,aACAA,KACGwI,IAEHnI,MAAMmI,GAtBDnQ,KAAA4C,KAAA,6BAEL5C,KAAA8C,YAAA,8PACF9C,KAAAiI,OAASC,IAAEC,OAAO,CAChBiK,iBAAkBlK,EAAAA,EACfE,SACAC,SACC,oIAEJzG,QAASsG,EAAAA,EAAEE,SAASC,SAAS,qCAC7BmH,kBAAmBtH,EAAEA,EAAAuB,UAAUnB,WAAW+J,SAAQ,KAalDrS,KAAKmS,UAAYA,EACjBnS,KAAK2H,aAAeA,EACpB3H,KAAKW,OAASC,EAAOA,OAAAiJ,YAAY,CAAEqF,OAAQ,+BAA+B,CAG5E,WAAgBpE,EAAMsH,iBACpBA,EAAAxQ,QACAA,EAAA4N,kBACAA,IAEM,MAAA8C,EAAetS,KAAK2H,aAAa4K,kBACvC,IAAKD,EACI,MAAA,sGAGT,MAAME,EACJxS,KAAK2H,aAAa8K,0BAA0BL,GAC9C,IAAKI,EACH,MAAO,mEAAmEJ,wDAG5E,MAAMV,EAAoBc,EAAWd,kBAC/BG,EAAkBW,EAAWX,gBAG7BjS,EAAa,GAAG0S,EAAa/Q,kBAAkB+Q,EAAavQ,YAElE/B,KAAKW,OAAOsD,KACV,wBAAwBrE,QAAiBiS,MAAoBW,EAAWZ,yCAAyCF,KAG/G,IAEI,MAAAhC,QAAuB1P,KAAKmS,UAAUhN,YAC1CuM,EACA9P,EACA,sBAAsB0Q,EAAa1P,QAGrC,IAAK8M,EACG,MAAA,IAAIvO,MAAM,0BAGlB,IAAKqO,EACI,MAAA,mBAAmBqC,MAAoBW,EAAWZ,mCAAmCF,uBAAuChC,IAG/H,MAAAgD,QAAkB1S,KAAKyP,iBAC3BiC,EACA9R,EACA8P,GAGF,OAAIgD,GACF1S,KAAKW,OAAOsD,KAAK,kBAAkB4N,IAAmBa,GAE/C,uBAAuBb,MAAoBa,KAI7C,mBAAmBb,MAAoBW,EAAWZ,mCAAmCF,uBAAuChC,UAC5H/N,GAIA,OAHP3B,KAAKW,OAAOgB,MACV,yCAAyC+P,MAAsB/P,KAE1D,4BAA4BkQ,MACjClQ,aAAiBR,MAAQQ,EAAMC,QAAUC,OAAOF,IAClD,CACF,CAGF,sBAAc8N,CACZrK,EACAxF,EACA8P,GAKA,OAA+B,CACzB,IACF,MAAM9J,QAAiB5F,KAAKmS,UAAU7L,iBAAiBlB,GAE5C,IAAA,MAAAxD,KAAWgE,EAASA,SAAU,CACvC,GACEhE,EAAQsE,gBAAkBwJ,GAC1B9N,EAAQyP,cAAgBzR,EAExB,SAIK,aAFeI,KAAKmS,UAAU5L,kBAAkB3E,EAAQyD,MAAQ,GAEhE,QAEF1D,GACP3B,KAAKW,OAAOgB,MAAM,+BAA+BA,IAAO,OAEpD,IAAIoO,SAASC,GAAYC,WAAWD,EAAS,MAAK,CAEnD,OAAA,IAAA,EC1HJ,MAAM2C,UAA+B7K,EAAAA,eAgB1C,WAAAnI,EAAYwS,UACVA,EAAAxK,aACAA,KACGwI,IAEHnI,MAAMmI,GApBDnQ,KAAA4C,KAAA,sBAEL5C,KAAA8C,YAAA,uMACF9C,KAAAiI,OAASC,IAAEC,OAAO,CAChByJ,gBAAiB1J,EAAAA,EACdE,SACAC,SACC,oFAcJrI,KAAKmS,UAAYA,EACjBnS,KAAK2H,aAAeA,EACpB3H,KAAKW,OAASC,EAAOA,OAAAiJ,YAAY,CAAEqF,OAAQ,0BAA0B,CAGvE,WAAgBpE,EAAM8G,gBACpBA,IAEM,MAAAU,EAAetS,KAAK2H,aAAa4K,kBACvC,IAAKD,EACI,MAAA,6GAGTtS,KAAKW,OAAOsD,KACV,8BAA8BqO,EAAavQ,gBAAgB6P,KAGzD,IACF5R,KAAKW,OAAOwQ,MAAM,0BAA0BS,QACtC,MAAAgB,QAAsB5S,KAAKmS,UAAUrQ,gBACzC8P,GAEE,IAACgB,GAAehM,WAAWC,aAC7B,MAAO,+EAA+E+K,4DAElF,MAAAE,EAAuBc,EAAchM,UAAUC,aAC/CgL,EACJe,EAAczL,QAAQvE,MAAQ,SAASgP,IAEnCiB,QAAsB7S,KAAKmS,UAAUlQ,wBACzC6P,EACAQ,EAAa1P,MAETkQ,EAAqBD,GAAerN,oBAC1C,IAAKsN,EACG,MAAA,IAAI3R,MAAM,iDAGd,IAAAM,EACA,IAEE,GADJA,EAAsBqR,EAAmBrN,WACrCsN,MAAMtR,GACF,MAAA,IAAIN,MAAM,2CAEX6R,GACP,MAAM,IAAI7R,MACR,yDAAyD6R,IAC3D,CAGF,MAAMC,EAAwB,IACxB3Q,EAAU,IACVD,EAAcgM,KAAK6E,KAAKD,EAAwB3Q,GAEhD6Q,QACEnT,KAAKmS,UAAUhQ,8BACnB2P,EACArQ,EACAY,EACAC,GAGA,IAAC6Q,GAAoBzB,kBACvB,MAAO,oDAAoDE,kBAAgCnQ,aACzFwR,EAAwB,eAI5B,MAAMvB,EAAoByB,EAAmBzB,kBAC7C1R,KAAKW,OAAOsD,KAAK,mCAAmCyN,KAEpD,MAAMC,EAAkC,CACtCC,kBACAC,kBACAC,uBACAJ,qBAEG1R,KAAA2H,aAAaoK,oBAAoBJ,GAEhC,MAAAyB,EAAcpT,KAAK2H,aAAa0L,kBAChCC,EAAaF,EAAYG,MAC5BC,GAAMA,EAAE9B,oBAAsBA,IAE3B+B,EAAoBH,EACtBF,EAAYM,QAAQJ,GAAc,EAClC,KAIJ,MAAO,uCAFUG,EAAoB,IAAIA,IAAsB,WAEA5B,MAAoBD,yBAAuCF,4DACnH/P,GAEA,OADP3B,KAAKW,OAAOgB,MAAM,iCAAiCA,KAC5C,oCAAoCiQ,MACzCjQ,aAAiBR,MAAQQ,EAAMC,QAAUC,OAAOF,IAClD,CACF,ECvHG,MAAMgS,UAA4B7L,EAAAA,eAqBvC,WAAAnI,EAAYgI,aAAEA,EAAAwK,UAAcA,KAAchC,IACxCnI,MAAMmI,GArBDnQ,KAAA4C,KAAA,mBAEL5C,KAAA8C,YAAA,wMACF9C,KAAAiI,OAASC,IAAEC,OAAO,CAChByL,eAAgB1L,EAAAA,EACbuB,UACAnB,WACAD,SACC,iEAEJwL,YAAa3L,EACVA,EAAAuB,UACAnB,WACAD,SAAS,oDASZrI,KAAK2H,aAAeA,EACpB3H,KAAKmS,UAAYA,EACjBnS,KAAKW,OAAS,IAAIC,EAAAA,OAAO,CAAEsO,OAAQ,uBAAuB,CAG5D,WAAgBpE,CAAMgJ,GACd,MAAAF,EAAiBE,EAAKF,iBAAkB,EACxCC,EAAcC,EAAKD,cAAe,EAElCT,QAAoBpT,KAAK+T,yBAE3B,GAAuB,IAAvBX,EAAY7H,OACP,MAAA,6CAGT,MAAMyI,EAAoBZ,EAAYxH,QACnC4H,GAAmB,gBAAbA,EAAES,SAGLC,EAAqBd,EAAYxH,QAAQ4H,GAAMA,EAAEW,YAEjDC,EAAoBhB,EAAYxH,QAAQ4H,GAAMA,EAAEY,oBAEtD,IAAIC,EAAS,GAyBb,OAvBIL,EAAkBzI,OAAS,IACnB8I,GAAA,0BAA0BL,EAAkBzI,aACpCyI,EAAA1P,SAAQ,CAACgQ,EAAMC,KAC/BF,GAAUrU,KAAKwU,iBAAiBF,EAAMC,EAAOX,MAErCS,GAAA,MAGRR,GAAeO,EAAkB7I,OAAS,IAClC8I,GAAA,wCAAwCD,EAAkB7I,aAClD6I,EAAA9P,SAAQ,CAACgQ,EAAMC,KAC/BF,GAAUrU,KAAKwU,iBAAiBF,EAAMC,EAAOX,MAErCS,GAAA,MAGRR,GAAeK,EAAmB3I,OAAS,IACnC8I,GAAA,kCAAkCH,EAAmB3I,aAC5C2I,EAAA5P,SAAQ,CAACgQ,EAAMC,KAChCF,GAAUrU,KAAKwU,iBAAiBF,EAAMC,EAAOX,OAI1CS,EAAOjI,MAAK,CAGb,gBAAAoI,CACNF,EACAC,EACAX,GAEA,IAAIS,EAAS,GAAGE,EAAQ,MACtBD,EAAKG,aAAaC,cAAgBJ,EAAKzC,iBAAmB,oBACvDyC,EAAK1C,qBAIVyC,GAAU,aAHaC,EAAKH,UACxB,oBACAG,EAAK5C,sBAKT,GAFA2C,GAAU,cADSC,EAAKL,QAAU,cAG9BL,EAAgB,CAOlB,GANIU,EAAKG,aAAaE,MACpBN,GAAU,WAAWC,EAAKG,YAAYE,IAAIC,UAAU,EAAG,OACrDN,EAAKG,YAAYE,IAAIpJ,OAAS,IAAM,MAAQ,QAI5C+I,EAAKtO,QAAS,CAIhBqO,GAAU,MAHWC,EAAKH,UACtB,eACA,6BAC6BG,EAAKtO,QAAQ6O,oBAAgB,CAG5DP,EAAKQ,eACPT,GAAU,qBAAqBC,EAAKQ,aAAaD,qBACnD,CAGK,OAAAR,CAAA,CAGT,4BAAcN,GACR,IAAC/T,KAAKmS,UACD,OAAAnS,KAAK2H,aAAa0L,kBAGvB,IACF,MAAMtR,UAAEA,GAAc/B,KAAKmS,UAAUnL,sBACrC,IAAKjF,EACI,OAAA/B,KAAK2H,aAAa0L,kBAGrB,MAAA0B,EAAoB/U,KAAK2H,aAAaqN,wBAC5C,IAAKD,EAEI,OADF/U,KAAAW,OAAOgB,MAAM,sCACX3B,KAAK2H,aAAa0L,kBAGrB,MAAAD,QAAoB2B,EAAkBE,oBAC1ClT,GAGF,IAAA,MAAWyQ,KAAcY,EAClBpT,KAAA2H,aAAauN,sBAAsB1C,GAGnC,OAAAY,QACAzR,GAEA,OADCwT,QAAAxT,MAAM,kCAAmCA,GAC1C3B,KAAK2H,aAAa0L,iBAAgB,CAC3C,EC5IG,MAAM+B,UAA0BtN,EAAAA,eAkCrC,WAAAnI,EAAYwS,UAAEA,EAAAxK,aAAWA,KAAiBwI,IACxCnI,MAAMmI,GAlCDnQ,KAAA4C,KAAA,iBACO5C,KAAA8C,YAAA,ycAKd9C,KAAAiI,OAASC,IAAEC,OAAO,CAChBiK,iBAAkBlK,EAAAA,EACfE,SACAC,SACC,0JAEJgN,YAAanN,IACVuB,UACAnB,WACA+J,SAAQ,GACRhK,SACC,qKAEJiN,kBAAmBpN,EAAAA,EAChBO,SACA8M,MACAC,WACAlN,WACAD,SACC,0GAUJrI,KAAKmS,UAAYA,EACjBnS,KAAK2H,aAAeA,EACpB3H,KAAKW,OAASC,EAAOA,OAAAiJ,YAAY,CAAEqF,OAAQ,qBAAqB,CAGlE,WAAgBpE,EAAMsH,iBACpBA,EAAAiD,YACAA,EAAAC,kBACAA,IAEA,MAAM9C,EACJxS,KAAK2H,aAAa8K,0BAA0BL,GAE9C,IAAKI,EACH,MAAO,mEAAmEJ,wDAG5E,MAAMV,EAAoBc,EAAWd,kBAC/BG,EAAkBW,EAAWX,gBAC7BtC,EACJvP,KAAK2H,aAAa8N,iBAAiB/D,GAErC1R,KAAKW,OAAOsD,KACV,yCAAyC4N,MAAoBW,EAAWZ,6BAA6BF,mBAAmC2D,iBAA2BC,aAA6B/F,MAG9L,IAEF,MACMqB,SADe5Q,KAAKmS,UAAUzM,YAAYgM,IACrB9L,SAE3B,IAAKgL,GAAsC,IAAvBA,EAAYrF,OAC9B,MAAO,yCAAyCmG,KAGlD,IAAIgE,EAA+C,GAC/CC,EAAuBpG,EAC3B,MAAMqG,GAAmC,IAAhBP,EAEzB,GAAIO,EAAkB,CACf5V,KAAAW,OAAOsD,KAAK,qDACjB,MAAM4R,EAAQP,GAAqB,EACfI,EAAA9E,EAAYkF,OAAOD,EAAK,MAE5C7V,KAAKW,OAAOsD,KACV,qCAAqCsL,KAEnBmG,EAAA9E,EAAYhF,QAAQkF,GACI,IAAhBA,EAAI/K,UACHwJ,IAGzBmG,EAAkBnK,OAAS,IAC7BoK,EAAuBD,EAAkBK,QACvC,CAACC,EAAOlF,IAAQzC,KAAKC,IAAI0H,EAAuB,IAAhBlF,EAAI/K,YACnCwJ,IAKH,GAA6B,IAA7BmG,EAAkBnK,OACpB,OAAOqK,EACH,wEAAwElE,KACxE,6CAA6CG,sBAGnD7R,KAAKW,OAAOsD,KAAK,cAAcyR,EAAkBnK,sBAG7C,IAAA0K,EAAeL,EACf,0BAA0B/D,OAE1B,qBAAqBA,OAGzB,IAAA,MAAWf,KAAO4E,EAAmB,CACnC,IAAI9F,EAAUkB,EAAIzL,KACd,IAEqB,iBAAZuK,GAAwBA,EAAQ9F,WAAW,YACpD9J,KAAKW,OAAOwQ,MAAM,gCAAgCvB,KAClDA,QAAgB5P,KAAKmS,UAAU5L,kBAAkBqJ,GACjD5P,KAAKW,OAAOwQ,MAAM,4BAA4BvB,GAASrE,WAIzD,IAAI2K,EAAiBtG,EACjB,IACF,MAAMuG,EAAShJ,KAAK2C,MAAMF,GAAW,MACrC,GACe,WAAbuG,EAAOC,GACO,YAAdD,EAAOpF,IACPoF,EAAO9Q,KACP,CAGA6Q,EAAiB,IADEC,EAAO9E,aAAe,sBACJ8E,EAAO9Q,MAAI,MAG/B6Q,EAAAtG,QAEZyG,GAEUH,EAAAtG,CAAA,CAIHqG,GAAA,MADI,IAAIlI,KAAK+C,EAAI/K,WACC8O,2BAChC/D,EAAI5K,qBAEdgQ,YAEevU,GACD,MAAA2O,EAAW,kCACfQ,EAAI5K,qBACAvE,aAAiBR,MAAQQ,EAAMC,QAAUC,OAAOF,KACjD3B,KAAAW,OAAOgB,MAAM2O,GACF2F,GAAA,oCAAoCnF,EAAI5K,oBAAe,CACzE,CAcF,OAVK0P,GAAoBD,EAAuBpG,IAC9CvP,KAAKW,OAAOwQ,MACV,gCAAgCO,QAAwBiE,KAE1D3V,KAAK2H,aAAa2O,gBAChB5E,EACAiE,IAIGM,EAAa7J,aACbzK,GAIA,OAHP3B,KAAKW,OAAOgB,MACV,sCAAsC+P,MAAsB/P,KAEvD,+BAA+BkQ,MACpClQ,aAAiBR,MAAQQ,EAAMC,QAAUC,OAAOF,IAClD,CACF,EC/KG,MAAM4U,UAA8BzO,EAAAA,eAsBzC,WAAAnI,EAAYwS,UAAEA,KAAchC,IAC1BnI,MAAMmI,GAtBDnQ,KAAA4C,KAAA,qBAEL5C,KAAA8C,YAAA,mIACF9C,KAAAiI,OAASC,IAAEC,OAAO,CAChBpG,UAAWmG,EAAAA,EACRE,SACAE,WACAD,SACC,qFAEJmO,KAAMtO,EAAAA,EACHM,MAAMN,EAAAA,EAAEuO,WAAWzL,sBACnB1C,WACAD,SACC,yEASJrI,KAAKmS,UAAYA,EACjBnS,KAAKW,OAASC,EAAOA,OAAAiJ,YAAY,CAAEqF,OAAQ,yBAAyB,CAGtE,WAAgBpE,EAAM/I,UACpBA,EAAAyU,KACAA,IAEAxW,KAAKW,OAAOsD,KACV,oDACAkJ,KAAKC,UAAU,CACbrL,YACAyU,UAIJ,MAAMzW,EAAqC,CAAC,EACxCgC,IACFhC,EAAQgC,UAAYA,GAElByU,GAAQA,EAAKjL,OAAS,IACxBxL,EAAQyW,KAAOA,GAETzW,EAAAD,QAAUE,KAAKmS,UAAU9Q,aAE7B,IACE,IAACrB,KAAKmS,UAAUlS,eAClB,MAAM,IAAIkB,MACR,yEAGJ,MAAM6D,QAAehF,KAAKmS,UAAUlS,eAAeyW,kBACjD3W,GAGF,IAAKiF,EAAO2B,SAAW3B,EAAOrD,MACrB,MAAA,gCACLqD,EAAOrD,OAAS,kBAIpB,IAAKqD,EAAO2R,eAAiD,IAAhC3R,EAAO2R,cAAcpL,OACzC,MAAA,gDAIT,IAAI8I,EAAS,SAASrP,EAAO2R,cAAcpL,4BAmB3C,OAlBAvG,EAAO2R,cAAcrS,SAAQ,CAACsS,EAAKrC,KACjC,MAAM/R,EAAWoU,EAAIpU,SACrB6R,GAAU,GAAGE,EAAQ,YAAY/R,EAASqU,OAAS,UACzCxC,GAAA,gBAAgB7R,EAASmS,KAAO,UAChCN,GAAA,kBAAkBuC,EAAI7U,cACtBsS,GAAA,cAAcuC,EAAI3C,WAC5BI,GAAU,aAAa7R,EAASkC,YAAYpB,OAAS,UACjDd,EAASkC,YAAY1B,cAAgBR,EAASkC,WAAW1B,aAAauI,OAAS,IACjF8I,GAAU,oBAAoB7R,EAASkC,WAAW1B,aAAaoM,KAAK,WAElE5M,EAASkC,aACX2P,GAAU,kBAAkBlH,KAAKC,UAAU5K,EAASkC,iBAE5C2P,GAAA,qBAAqBuC,EAAIrV,mBACzB8S,GAAA,sBAAsBuC,EAAIxU,oBAC1BiS,GAAA,kBAAkBuC,EAAIE,iBAG3BzC,EAAOjI,aACPzK,GAEP,OADA3B,KAAKW,OAAOgB,MAAM,wCAAwCA,KACnD,kCACLA,aAAiBR,MAAQQ,EAAMC,QAAUC,OAAOF,IAClD,CACF,EC7EG,MAAMoV,UAA8BjP,EAAAA,eAkEzC,WAAAnI,EAAYwS,UACVA,EAAAxK,aACAA,KACGwI,IAEHnI,MAAMmI,GAtEDnQ,KAAA4C,KAAA,sBAEL5C,KAAA8C,YAAA,6MACF9C,KAAAiI,OAASC,IAAEC,OAAO,CAChB6O,UAAW9O,EAAAA,EACRuB,UACAnB,WACAD,SACC,uFAEJuJ,gBAAiB1J,EAAAA,EACdE,SACAE,WACAD,SACC,+EAEJe,SAAUlB,EACPA,EAAAM,MACCN,EAAAA,EAAEC,OAAO,CACPe,OAAQhB,IAAEO,SACVY,iBAAkBnB,EAAAA,EAAEE,SAASE,cAGhCA,WACAD,SACC,uFAEJiB,UAAWpB,EACRA,EAAAM,MACCN,EAAAA,EAAEC,OAAO,CACPe,OAAQhB,IAAEO,SACVU,QAASjB,IAAEE,SACXiB,iBAAkBnB,EAAAA,EAAEE,SAASE,cAGhCA,WACAD,SACC,gGAEJkB,iBAAkBrB,IACfM,MAAMN,EAAAA,EAAEE,UACRE,WACAD,SACC,qEAEJ4O,uBAAwB/O,EAAAA,EACrBO,SACAH,WACAD,SACC,wEAEJ6O,wBAAyBhP,EAAAA,EACtBE,SACAE,WACAD,SACC,uGAONrI,KAAQoQ,cAAwB,EAS9BpQ,KAAKmS,UAAYA,EACjBnS,KAAK2H,aAAeA,EACf3H,KAAAW,OAASC,SAAOiJ,YAAY,CAC/BqF,OAAQ,wBACRrO,MAAO,UAEJb,KAAAmX,oBAAsB,IAAIxD,EAAoB,CACjDhM,eACAwK,eACGhC,GACJ,CAGH,YAAAiH,CAAaC,GACXrX,KAAKmS,UAAYkF,EACZrX,KAAAW,OAAOsD,KAAK,0DACZjE,KAAAmX,oBAAsB,IAAIxD,EAAoB,CACjDhM,aAAc3H,KAAK2H,aACnBwK,UAAWkF,GACZ,CAGH,WAAgBvM,EAAMkM,UACpBA,GAAY,EAAApF,gBACZA,EAAAxI,SACAA,EAAW,GAACE,UACZA,EAAY,GAACC,iBACbA,EAAA0N,uBACAA,EAAyB,GAAAC,wBACzBA,IAGA,IADqBlX,KAAK2H,aAAa4K,kBAE9B,MAAA,iHAGT,GAAIvS,KAAKoQ,aACA,MAAA,0GAGL,IACFpQ,KAAKoQ,cAAe,EACpB,MAAM7O,QAAuBvB,KAAKmS,UAAU1L,oBAE5C,IAAKlF,EAEI,OADPvB,KAAKoQ,cAAe,EACb,gEAGTpQ,KAAKW,OAAOsD,KACV,qCAAqC1C,gCAGvC,MAAMG,EAAY1B,KAAKsX,gBACrBlO,EACAE,EACAC,EACAqI,EACAsF,GAGIK,EAAUxJ,KAAKyJ,MAAiC,IAAzBP,EACvBQ,EAAiB,IACvB,IAAIC,EAAqB,EACrBC,EAA0B,EAC1BC,EAAsB,EACtBC,EAAkB,EAEf,KAAA9J,KAAKyJ,MAAQD,GACd,UACIvX,KAAKmX,oBAAoBW,OAAO,CACpClE,gBAAgB,EAChBC,aAAa,IAET,MAAAkE,EAAqB/X,KAAK2H,aAAa0L,kBAGvC2E,MAAqCC,IAE3CF,EACGnM,QAAQ0I,GAAyB,gBAAhBA,EAAKL,SAA6BK,EAAKH,YACxD7P,SAASgQ,IACH0D,EAA+BzG,IAAI+C,EAAK1C,kBACZoG,EAAAE,IAC7B5D,EAAK1C,oBACDjB,KAIJ2D,EAAK7S,qBAEJuW,EAAA/N,IAAIqK,EAAK1C,kBACRH,IAAI5P,OAAOyS,EAAK7S,yBAIpB,MAGA0W,SAHuBnY,KAAKmS,UAAUzM,YAC1CnE,IAEiCqE,SAASgG,QAAQkF,MAE/CA,EAAI5K,iBACL4K,EAAI5K,iBAAmBwR,KAIzBA,EAAqBrJ,KAAKC,IACxBoJ,EACA5G,EAAI5K,iBAEY,uBAAX4K,EAAIC,MAGb,IAAA,MAAWqH,KAAWD,EAAa,CACjC,MAAME,EAAYD,EAAQlS,gBAC1B,IAAKmS,EACH,SAGFV,IAGA,MAAMpW,QACGvB,KAAKmS,UAAU1L,qBAAwB,GAG1C6R,EACJtY,KAAK2H,aAAaqN,wBACpB,IAAKsD,EAAoB,CACvBtY,KAAKW,OAAOgB,MACV,uDAEF,QAAA,CAIF,GACE2W,EAAmBC,6BACjBhX,EACA8W,GAEF,CACArY,KAAKW,OAAOsD,KACV,YAAYoU,iCAEdR,IACA,QAAA,CAGI,MAAAW,EAAqBxY,KAAKyY,iBAAiBL,GACjD,IAAKI,EAAoB,CAEJF,EAAAI,+BACjBnX,EACA8W,GAEF,QAAA,CAGE,GAAAzG,GAAmB4G,IAAuB5G,EAAiB,CAC7D5R,KAAKW,OAAOsD,KACV,YAAYoU,0BAAkCzG,KAEhD,QAAA,CAII,MAAA+G,EACJX,EAA+B/N,IAAIuO,GACrC,GAAIG,GAA4BpH,IAAI1P,OAAOwW,IACzCrY,KAAKW,OAAOsD,KACV,yCAAyCoU,UAAkBG,eAE1CF,EAAAI,+BACjBnX,EACA8W,GAEFR,SAIF,GAAIb,EAAW,CACP,MAAAhS,QAAehF,KAAK4Y,wBACxBP,EACAG,EACA9W,GAEiB4W,EAAAI,+BACjBnX,EACA8W,GAGErT,EAAO2B,UACTiR,IACA5X,KAAKW,OAAOsD,KACV,yCAAyCuU,kBAAmCH,KAEhF,MAEArY,KAAKW,OAAOsD,KACV,kBAAkBoU,UAAkBG,yBAExC,OAGI,IAAIzI,SAASC,GAAYC,WAAWD,EAASyH,WAC5C9V,GACP3B,KAAKW,OAAOgB,MAAM,+BAA+BA,WAC3C,IAAIoO,SAASC,GAAYC,WAAWD,EAASyH,IAAe,CAMtE,OAFAzX,KAAKoQ,cAAe,EAEY,IAA5BuH,EACK,8CAA8CV,8BAC5CD,EACF,iBAAiBC,oBAAyCU,mCAAyDC,0BAA4CC,yBAAuC7X,KAAK6Y,gBAChNzP,EACAE,MAGK,iBAAiB2N,oBAAyCU,yFAE5DhW,GAGP,OAFA3B,KAAKoQ,cAAe,EACpBpQ,KAAKW,OAAOgB,MAAM,iCAAiCA,KAC5C,qCACLA,aAAiBR,MAAQQ,EAAMC,QAAUC,OAAOF,IAClD,CACF,CAGM,eAAA2V,CACNlO,EAA4B,GAC5BE,EAAkC,GAClCC,EACAqI,EACAsF,GAEA,GAAwB,IAApB9N,EAASmC,QAAqC,IAArBjC,EAAUiC,OAInC,IACF,MAAMuN,EAAiB9Y,KAAKmS,UAAUnL,sBAAsBjF,UACtDgX,EAAmB7B,GAA2B4B,EAE9CrW,EAAU,IAAIkJ,mBAAiB,CACnC7L,QAASE,KAAKmS,UAAU9Q,aACxBV,OAAQX,KAAKW,OACbqY,0BAA2BD,IAGvBE,EAAY,IAAK1P,GAAoB,IACvCqI,IAAoBqH,EAAUlS,SAAS6K,IACzCqH,EAAUC,KAAKtH,GAGjB,IAAA,MAAW5I,KAAWI,EAChB,GAAAJ,EAAQE,OAAS,EAAG,CAChB,MAAAiQ,EAAYnQ,EAAQK,kBAAoB0P,EAC9CtW,EAAQsJ,WAAW/C,EAAQE,OAAQiQ,EAAWF,GAC9CjZ,KAAKW,OAAOsD,KACV,mBAAmB+E,EAAQE,kCAAkCiQ,IAC/D,CAIJ,IAAA,MAAWlQ,KAAYK,EACrB,GAAIL,EAASC,OAAS,GAAKD,EAASE,QAAS,CACrC,MAAAgQ,EAAYlQ,EAASI,kBAAoB0P,EACvCtW,EAAAyJ,YACNjD,EAASC,OACTD,EAASE,QACTgQ,OACA,EACAF,GAEFjZ,KAAKW,OAAOsD,KACV,oBAAoBgF,EAASC,mBAAmBD,EAASE,8BAA8BgQ,IACzF,CAIG,OAAA1W,QACAd,GAEA,YADP3B,KAAKW,OAAOgB,MAAM,qCAAqCA,IAChD,CACT,CAGM,gBAAA8W,CAAiBL,GACvB,GAAIA,EAAQ/G,YACH,OAAArR,KAAKmS,UAAUlS,eAAemZ,6BACnChB,EAAQ/G,YAGL,CAGT,6BAAcuH,CACZnX,EACAD,EACAE,GAEI,IACF,MAAMH,QAAuBvB,KAAKmS,UAAU1L,oBAC5CzG,KAAKW,OAAOsD,KACV,iCAAiCxC,UAA4BD,KAGzD,MAAAwD,QAAehF,KAAKmS,UAAU7Q,wBAClCC,EACAC,EACAC,EACAC,GAGE,IAACsD,GAAQ0M,kBACJ,MAAA,CACL/K,SAAS,EACThF,MAAO,yDAIX,MAAM+P,EAAoB1M,EAAO0M,kBAK7B,IAAA+C,EAJJzU,KAAKW,OAAOsD,KACV,qCAAqCyN,KAInC,IACI,MAAAvK,QAAgBnH,KAAKmS,UAAUrQ,gBACnCN,GAEE2F,EAAQR,SAAWQ,EAAQA,UAC7BsN,EAActN,EAAQA,eAEjBkS,GACPrZ,KAAKW,OAAOqD,KACV,+BAA+BxC,MAAwB6X,IACzD,CAGI,MAAAvH,SACG9R,KAAKmS,UAAUrQ,gBAAgBN,KAAuBoF,WACzDC,cAAgB,GAEhB2L,EAA+B,CACnCZ,gBAAiBpQ,EACjBqQ,gBACE4C,GAAaC,cAAgB,SAASlT,IACxCsQ,uBACAJ,oBACA+C,cACAzO,YAAa+H,KACbkG,OAAQ,cACRzR,SAAU,CACR6V,UAAW5W,IAMR,OAFFzB,KAAA2H,aAAaoK,oBAAoBS,GAE/B,CACL7L,SAAS,EACT+K,2BAEK/P,GAEA,OADP3B,KAAKW,OAAOgB,MAAM,uCAAuCA,KAClD,CACLgF,SAAS,EACThF,MAAOA,aAAiBR,MAAQQ,EAAMC,QAAUC,OAAOF,GACzD,CACF,CAGM,eAAAkX,CACNzP,EAA4B,GAC5BE,EAAkC,IAElC,GAAwB,IAApBF,EAASmC,QAAqC,IAArBjC,EAAUiC,OAC9B,MAAA,GAGT,IAAI+N,EAAY,eAEZ,GAAAlQ,EAASmC,OAAS,EAAG,CACjB,MAAAgO,EAAiBnQ,EACpBwC,QAAQI,GAAQA,EAAI9C,OAAS,IAC7BrD,KAAKmG,IACJ,MAAMmN,EAAYnN,EAAI3C,iBAClB,OAAO2C,EAAI3C,mBACX,GACJ,MAAO,GAAG2C,EAAI9C,cAAciQ,OAE7B/J,KAAK,MAEJmK,IACWD,GAAAC,EACf,CAGE,GAAAjQ,EAAUiC,OAAS,EAAG,CACpBnC,EAASmC,OAAS,IACP+N,GAAA,SAGf,MAAME,EAAkBlQ,EACrBsC,QAAQI,GAAQA,EAAI9C,OAAS,GAAK8C,EAAI7C,UACtCtD,KAAKmG,IACJ,MAAMmN,EAAYnN,EAAI3C,iBAClB,OAAO2C,EAAI3C,mBACX,GACJ,MAAO,GAAG2C,EAAI9C,mBAAmB8C,EAAI7C,UAAUgQ,OAEhD/J,KAAK,MAEJoK,IACWF,GAAAE,EACf,CAGK,MAAc,iBAAdF,EAA+B,GAAKA,CAAA,CAQtC,MAAAG,GAELzZ,KAAKmX,oBACFW,OAAO,CACNlE,gBAAgB,EAChBC,aAAa,IAEdrD,OAAO7O,IACN3B,KAAKW,OAAOgB,MAAM,+BAA+BA,OAClD,ECphBA,MAAM+X,UAAqC5R,EAAAA,eAwBhD,WAAAnI,EAAYwS,UACVA,EAAAxK,aACAA,KACGwI,IAEHnI,MAAMmI,GA5BDnQ,KAAA4C,KAAA,6BAEL5C,KAAA8C,YAAA,iMACF9C,KAAAiI,OAASC,IAAEC,OAAO,CAChBwR,OAAQzR,IACLK,KAAK,CAAC,OAAQ,OAAQ,WACtBF,SACC,qGAEJuR,WAAY1R,EAAAA,EACTE,SACAE,WACAD,SACC,qFAONrI,KAAQ6Z,gBAA0B,EAClC7Z,KAAQ8Z,kBAAoB,IAQ1B9Z,KAAKmS,UAAYA,EACjBnS,KAAK2H,aAAeA,EACf3H,KAAAW,OAASC,SAAOiJ,YAAY,CAC/BqF,OAAQ,+BACRrO,MAAO,SACR,CAGH,WAAgBiK,EAAM6O,OACpBA,EAAAC,WACAA,IAGA,IADqB5Z,KAAK2H,aAAa4K,kBAE9B,MAAA,oHAGT,IAAgB,SAAXoH,GAAgC,WAAXA,SAAuC,IAAfC,EAChD,MAAO,2CAA2CD,oEAGhD,IAGF,aAFM3Z,KAAK+Z,0BAEHJ,GACN,IAAK,OACH,OAAO3Z,KAAKga,eACd,IAAK,OACI,OAAAha,KAAKia,YAAYL,GAC1B,IAAK,SACI,OAAA5Z,KAAKka,cAAcN,GAC5B,QACE,MAAO,8BAA8BD,WAElChY,GAEP,OADA3B,KAAKW,OAAOgB,MAAM,0CAA0CA,KACrD,uCACLA,aAAiBR,MAAQQ,EAAMC,QAAUC,OAAOF,IAClD,CACF,CAGF,6BAAcoY,GACN,MAAAvC,EAAMzJ,KAAKyJ,MACbA,EAAMxX,KAAK6Z,gBAAkB7Z,KAAK8Z,0BAC9B9Z,KAAKma,kBACXna,KAAK6Z,gBAAkBrC,EACzB,CAGF,qBAAc2C,GACR,IACF,MAAMpY,UAAEA,GAAc/B,KAAKmS,UAAUnL,sBACrC,IAAKjF,EACG,MAAA,IAAIZ,MAAM,oDAGZ,MAAA4T,EAAoB/U,KAAK2H,aAAaqN,wBAC5C,IAAKD,EACG,MAAA,IAAI5T,MAAM,4CAGZ4T,EAAkBE,oBAAoBlT,SACrCJ,GAED,MADN3B,KAAKW,OAAOgB,MAAM,yCAAyCA,KACrDA,CAAA,CACR,CAGM,YAAAqY,GACA,MAAA1B,EAAqBtY,KAAK2H,aAAaqN,wBAC7C,IAAKsD,EACI,MAAA,4CAGH,MAIA8B,EAAc,IAJI9B,EAAmB+B,wBAEzC/B,EAAmBgC,qCAIjB,GAAuB,IAAvBF,EAAY7O,OAEP,OADC4J,QAAAoF,IAAI,wCAAyCH,GAC9C,wCAGL,IAAA/F,EAAS,SAAS+F,EAAY7O,4CAgC3B,MA/BgB,IAAI6O,GAAajU,MACtC,CAACC,EAAGC,IAAMA,EAAEL,QAAQC,UAAYG,EAAEJ,QAAQC,YAG7B3B,SAAQ,CAAC8T,EAAS7D,KAEzB,MAAAiG,EAAcpC,EAAQhE,kBAAoB,cAAgB,cAC1DqG,EAAmBrC,EAAQsC,kBAC/B,GAAGtC,EAAQ3W,qBAAuB2W,EAAQuC,kBAAoB,YAEhEtG,GAAU,GAAGE,EAAQ,MAAMiG,YAAsBC,MACjDpG,GAAU,MAAM+D,EAAQhE,kBAAoB,OAAS,SACnDgE,EAAQvG,iBAAmB,SAASuG,EAAQxG,sBACzCwG,EAAQxG,qBACbyC,GAAU,iBAAiB+D,EAAQpS,QAAQ6O,qBAEvCuD,EAAQlW,OACAmS,GAAA,YAAY+D,EAAQlW,UAG5BkW,EAAQ3D,aAAe2D,EAAQ3D,YAAYE,MACnCN,GAAA,WAAW+D,EAAQ3D,YAAYE,SAGjCN,GAAA,QAIVA,GAAA,0FAEAA,GAAA,yEACKA,CAAA,CAGD,WAAA4F,CAAYL,GACZ,MAAAtB,EAAqBtY,KAAK2H,aAAaqN,wBAC7C,IAAKsD,EACI,MAAA,4CAGH,MAOAF,EAHc,IAJIE,EAAmB+B,wBAEzC/B,EAAmBgC,qCAKO/G,MACzBqH,GACEA,EAAEF,mBAAqBd,GACvBgB,EAAEnZ,qBAAqBL,aAAewY,GACtCgB,EAAED,kBAAkBvZ,aAAewY,IAGxC,IAAKxB,EACH,MAAO,2BAA2BwB,oCAI9B,MAAAY,EAAcpC,EAAQhE,kBAAoB,WAAa,WACvDyG,EAAYzC,EAAQsC,kBACxB,GAAGtC,EAAQ3W,qBAAuB2W,EAAQuC,kBAAoB,YAEhE,IAAItG,EAAS,eAAemG,yBAAmCK,QAiCxD,OAhCPxG,GAAU,GAAG+D,EAAQhE,kBAAoB,YAAc,gBAAgBgE,EAAQxG,oBACrEyC,GAAA,GAAG+D,EAAQhE,kBAAoB,YAAc,kBACrDgE,EAAQvG,iBAAmB,SAASuG,EAAQxG,sBAE9CyC,GAAU,aAAa+D,EAAQpS,QAAQ6O,qBAEnCuD,EAAQlW,OACAmS,GAAA,SAAS+D,EAAQlW,UAGzBkW,EAAQ3D,cACAJ,GAAA,kCAEN+D,EAAQ3D,YAAYC,cAAgB0D,EAAQ3D,YAAYoC,SAC1DxC,GAAU,SACR+D,EAAQ3D,YAAYC,cAAgB0D,EAAQ3D,YAAYoC,gBAI3B,IAA7BuB,EAAQ3D,YAAYrR,OACZiR,GAAA,SAAS+D,EAAQ3D,YAAYrR,UAGrCgV,EAAQ3D,YAAYE,MACZN,GAAA,QAAQ+D,EAAQ3D,YAAYE,UAIhCN,GAAA,eACVA,GAAU,0DAA0DwG,OAElExG,GAAA,wEACKA,CAAA,CAGT,mBAAc6F,CAAcN,GACpB,MAAAtB,EAAqBtY,KAAK2H,aAAaqN,wBAC7C,IAAKsD,EACI,MAAA,4CAGH,MAOAF,EAHc,IAJIE,EAAmB+B,wBAEzC/B,EAAmBgC,qCAKO/G,MACzBqH,GACEA,EAAEF,mBAAqBd,GACvBgB,EAAEnZ,qBAAqBL,aAAewY,GACtCgB,EAAED,kBAAkBvZ,aAAewY,IAGxC,OAAKxB,GAKDA,EAAQuC,iBAESrC,EAAAI,+BACjBN,EAAQtG,sBAAwB,GAChCsG,EAAQuC,kBAEDvC,EAAQ3W,qBAEE6W,EAAAI,+BACjBN,EAAQ0C,eAAiB,GACzB1C,EAAQ3W,qBAIL,2BACL2W,EAAQvG,iBAAmB,SAASuG,EAAQxG,mCAnBrC,2BAA2BgI,mCAoBpC,EClQG,MAAMmB,UAAoCjT,EAAAA,eA4B/C,WAAAnI,EAAYwS,UACVA,EAAAxK,aACAA,KACGwI,IAEHnI,MAAMmI,GAhCDnQ,KAAA4C,KAAA,4BAEL5C,KAAA8C,YAAA,0GACF9C,KAAAiI,OAASC,IAAEC,OAAO,CAChByR,WAAY1R,EAAAA,EACTE,SACAC,SACC,mJAEJW,QAASd,EAAAA,EACNO,SACAH,WACAD,SACC,oGAEJkB,iBAAkBrB,IACfM,MAAMN,EAAAA,EAAEE,UACRE,WACAD,SACC,kGAcJrI,KAAKmS,UAAYA,EACjBnS,KAAK2H,aAAeA,EACf3H,KAAAW,OAASC,SAAOiJ,YAAY,CAC/BqF,OAAQ,+BACT,CAGH,WAAgBpE,EAAM8O,WACpBA,EAAA5Q,QACAA,EAAAO,iBACAA,IAEM,MAAA+I,EAAetS,KAAK2H,aAAa4K,kBACvC,IAAKD,EACI,MAAA,mHAGH,MAAAgG,EAAqBtY,KAAK2H,aAAaqN,wBAC7C,IAAKsD,EACI,MAAA,kDAGHA,EAAmBrD,oBAAoB3C,EAAavQ,WAG1D,MAKMqW,EALc,IACfE,EAAmB+B,wBACnB/B,EAAmBgC,qCAGI/G,MACzBqH,GAAOA,EAAEF,mBAAqBd,GAC5BgB,EAAEnZ,qBAAqBL,aAAewY,GACtCgB,EAAED,kBAAkBvZ,aAAewY,IAGxC,IAAKxB,EACH,MAAO,2BAA2BwB,0GAI9B,MAAAoB,EAAmB5C,EAAQ3W,qBAAuB2W,EAAQuC,iBAChE,IAAKK,EACH,MAAO,0EAA0EpB,KAG/E,IACF,MAAMrY,QAAuBvB,KAAKmS,UAAU1L,oBAC5C,IAAIiF,EAEA,GAAA1C,GAAWA,EAAU,EAAG,CAC1B,MAAMyC,EAAczL,KAAKmS,UAAUnL,sBAAsBjF,UACrD,IACiB2J,EAAA,IAAIC,EAAAA,iBAAiB,CACtC7L,QAASE,KAAKmS,UAAU9Q,aACxBV,OAAQX,KAAKW,OACbqY,0BAA2BvN,IAG7B,MAAMwP,EAAkB,IAClB1R,GAAoB,GACxB+I,EAAavQ,WAEE2J,EAAAK,WAAW/C,EAASyC,EAAawP,GAClDjb,KAAKW,OAAOsD,KACV,qBAAqB+E,6BAAmCyC,WAEnDyP,GACPlb,KAAKW,OAAOgB,MACV,qCAAqCuZ,KAGpBxP,OAAA,EACnB1L,KAAKW,OAAOqD,KACV,wEACF,CACF,CAGFhE,KAAKW,OAAOsD,KACV,qCAAqC2V,UAAmBoB,WAA0B5C,EAAQxG,mBAEtF,MAAA5M,QAAehF,KAAKmS,UAAU7Q,wBAClCC,EACA6W,EAAQxG,gBACRoJ,EACAtP,GAGE,IAAC1G,GAAQ0M,kBACX,MAAO,uDAAuDkI,mDAEhE5Z,KAAKW,OAAOsD,KACV,0CAA0Ce,EAAO0M,qBAGnD,MAAMA,EAAoB1M,EAAO0M,kBAEjC,IAAIyJ,EAAqB,GACrB,IACF,MAAMC,QAA0Bpb,KAAKmS,UAAUlS,eAAe+B,gBAAgBoW,EAAQxG,iBAEpFuJ,EAAAC,GAAmBxU,WAAWC,cAAgB,GAC3CsU,GACHnb,KAAKW,OAAOqD,KACV,8CAA8CoU,EAAQxG,yBAGnDyJ,GACPrb,KAAKW,OAAOqD,KACV,2CAA2CoU,EAAQxG,oBAAoByJ,IACzE,CAGI,MAAAzY,EAAOwV,EAAQ3D,aAAaC,cAAgB0D,EAAQ3D,aAAaoC,OAAS,SAASuB,EAAQxG,kBAC3FD,EAAkC,CACtCC,gBAAiBwG,EAAQxG,gBACzBC,gBAAiBjP,EACjBkP,qBAAsBqJ,EACtBzJ,oBACA+C,YAAa2D,EAAQ3D,YACrBzO,YAAa+H,KACbkG,OAAQ,eAGLjU,KAAA2H,aAAaoK,oBAAoBJ,GACnB2G,EAAArD,oBAAoBmD,EAAQxG,iBAE/C5R,KAAKW,OAAOsD,KAAK,mBAAmB2V,2BAEpC,IAAI5M,EAAa,GACbhE,GAAWA,EAAU,GAAK0C,IAC5BsB,EAAa,WAAWhE,0BAI1B,MAAO,4CADYoP,EAAQsC,kBAAoBd,UACuBhX,KAAQoK,uCAAgD0E,WACvH/P,GAKA,OAJP3B,KAAKW,OAAOgB,MACV,sCAAsCiY,MAAejY,KAGhD,sCAAsCiY,MAC3CjY,aAAiBR,MAAQQ,EAAMC,QAAUC,OAAOF,IAClD,CACF,ECxLG,MAAM2Z,UAA4BxT,EAAAA,eA2BvC,WAAAnI,CAAYoI,GACJC,QA3BDhI,KAAA4C,KAAA,mBAEL5C,KAAA8C,YAAA,qNAKF9C,KAAAiI,OAASC,IAAEC,OAAO,CAChBpG,UAAWmG,EAAAA,EACRE,SACAE,WACAD,SACC,iIAEJkT,aAAcrT,EAAAA,EACXuB,UACAnB,WACAD,SACC,6EAUJrI,KAAK+H,OAASA,EACT/H,KAAAW,OAASC,SAAOiJ,YAAY,CAAEqF,OAAQlP,KAAK4C,MAAM,CAQxD,WAAMkI,CAAMC,GACN,IAAA6G,EACA,IAQF,GAPI7G,EAAMhJ,UACR6P,EAAkB7G,EAAMhJ,WAEnB/B,KAAAW,OAAOsD,KAAK,sDACC2N,EAAA5R,KAAK+H,OAAOhH,kBAG3B6Q,EACG,MAAA,IAAIzQ,MAAM,0CAGlBnB,KAAKW,OAAOsD,KACV,+CAA+C2N,uBAAqC7G,EAAMwQ,gBAI5F,MAAMvW,QAAehF,KAAK+H,OAAO9H,eAAe+B,gBAC9C4P,EACA7G,EAAMwQ,cAGJ,GAAAvW,EAAO2B,SAAW3B,EAAOmC,QAK3B,OAJAnH,KAAKW,OAAOsD,KACV,sCAAsC2N,MAGjCzE,KAAKC,UAAUpI,EAAOmC,QAAS,KAAM,GACvC,CACL,MAAMqU,EAAe,gCAAgC5J,MACnD5M,EAAOrD,OAAS,kCAGX,OADF3B,KAAAW,OAAOgB,MAAM6Z,GACXA,CAAA,QAEF7Z,GACD,MACA6Z,EAAe,2CADFzQ,EAAMhJ,WAAa,uBAEpCJ,aAAiBR,MAAQQ,EAAMC,QAAUC,OAAOF,KAG3C,OADF3B,KAAAW,OAAOgB,MAAM6Z,EAAc7Z,GACzB6Z,CAAA,CACT,EC1EG,MAAMC,UAA6C3T,EAAAA,eAuBxD,WAAAnI,EAAYwS,UACVA,EAAAxK,aACAA,KACGwI,IAEHnI,MAAMmI,GA3BDnQ,KAAA4C,KAAA,sCAEL5C,KAAA8C,YAAA,6JACF9C,KAAAiI,OAASC,IAAEC,OAAO,CAChBuT,OAAQxT,EACLA,EAAAK,KAAK,CAAC,WAAY,YAAa,WAAY,cAC3CD,WACAD,SACC,sFAEJsT,MAAOzT,EAAAA,EACJO,SACAH,WACAD,SACC,uEAcJrI,KAAKmS,UAAYA,EACjBnS,KAAK2H,aAAeA,EACf3H,KAAAW,OAASC,SAAOiJ,YAAY,CAC/BqF,OAAQ,0BACRrO,MAAO,SACR,CAGH,WAAgBiK,EAAM4Q,OACpBA,EAAS,YAAAC,MACTA,IAGA,IADqB3b,KAAK2H,aAAa4K,kBAE9B,MAAA,+GAGL,IACI,MAAAqJ,QAAwB5b,KAAK6b,yBACnC,OAAO7b,KAAK8b,mBAAmBF,EAAiBF,EAAQC,SACjDha,GAEP,OADA3B,KAAKW,OAAOgB,MAAM,YAAY3B,KAAK4C,SAASjB,KACrC,mCACLA,aAAiBR,MAAQQ,EAAMC,QAAUC,OAAOF,IAClD,CACF,CAOF,4BAAcka,GACN,MAAAvD,EAAqBtY,KAAK2H,aAAaqN,wBAC7C,IAAKsD,EACH,MAAO,GAEH,MAAAhG,EAAetS,KAAK2H,aAAa4K,kBACvC,IAAKD,EACH,MAAO,SAGHgG,EAAmBrD,oBAAoB3C,EAAavQ,WAI1D,MAAO,IAHiBuW,EAAmB+B,wBACJ/B,EAAmBgC,oCAEG,CAMvD,kBAAAwB,CACNC,EACAL,EACAC,GAEI,GAAoB,IAApBI,EAASxQ,OACJ,MAAA,+DAGT,MAAMyQ,EAAiBhc,KAAKic,aAAaF,EAAUL,GAC7CQ,EAAkBP,EACpBK,EAAelG,MAAM,EAAG6F,GACxBK,EAEA,IAAA3H,EAAS,SAAS0H,EAASxQ,4CAyBxB,OAvBS2Q,EAAA5X,SAAQ,CAAC8T,EAAS7D,KAChC,MAAM4H,EACe,uBAAnB/D,EAAQnE,OACJ,cACA,cACNI,GAAU,GAAGE,EAAQ,MAAM4H,WAAyB/D,EAAQsC,qBAClDrG,GAAA,MACW,uBAAnB+D,EAAQnE,OAAkC,QAAU,WAClDmE,EAAQvG,oBAAoBuG,EAAQxG,qBACxCyC,GAAU,iBAAiB+D,EAAQpS,QAAQ6O,qBACvCuD,EAAQlW,OACAmS,GAAA,YAAY+D,EAAQlW,UAE5BkW,EAAQ3D,aAAaE,MACvBN,GAAU,WAAW+D,EAAQ3D,YAAYE,IAAIC,UAAU,EAAG,OACxDwD,EAAQ3D,YAAYE,IAAIpJ,OAAS,IAAM,MAAQ,QAGzC8I,GAAA,QAIVA,GAAA,6EACKA,CAAA,CAMD,YAAA4H,CACNF,EACAL,GAEM,MAAAU,EAAe,IAAIL,GAEzB,OAAQL,GACN,IAAK,WACH,OAAOU,EAAajW,MAClB,CAACC,EAAGC,IAAMD,EAAEJ,QAAQC,UAAYI,EAAEL,QAAQC,YAE9C,IAAK,YAYL,QACE,OAAOmW,EAAajW,MAClB,CAACC,EAAGC,IAAMA,EAAEL,QAAQC,UAAYG,EAAEJ,QAAQC,YAV9C,IAAK,WACH,OAAOmW,EAAajW,MAAK,CAACC,EAAGC,IAC3BD,EAAEyL,iBAAiBwK,cAAchW,GAAGwL,iBAAmB,KAAO,IAElE,IAAK,YACH,OAAOuK,EAAajW,MAAK,CAACC,EAAGC,IAC3BA,EAAEwL,iBAAiBwK,cAAcjW,GAAGyL,iBAAmB,KAAO,IAMpE,ECjKG,MAAMyK,EAAgBxT,EAAKsG,KAAK5O,QAAQ+b,MAAO,QCa/C,MAAMC,EAYX,WAAA7c,CAAYI,GAXZC,KAAQsS,aAAuC,KAC/CtS,KAAQyc,4BAAsD,CAAC,EAG/Dzc,KAAQsY,mBAAiD,KAavDtY,KAAK0c,mBAAqB3c,GAAS2c,mBAC9B1c,KAAA2c,cAAgB5c,GAAS4c,eAAiB,OAC/C,MAAMpc,EAAgBR,GAAS6c,gBAAkD,SAAhCpc,QAAQC,IAAIC,gBACxDV,KAAAW,OAAS,IAAIC,SAAO,CAAEsO,OAAQ,kBAAmBpO,OAAQP,IAG1DR,GAASwN,YACNvN,KAAA4H,6BAA6B7H,EAAQwN,WAC5C,CAOF,4BAAA3F,CACE2F,GAWA,OATKvN,KAAKsY,mBAOHtY,KAAAW,OAAOwQ,MAAM,2CANbnR,KAAAW,OAAOwQ,MAAM,mCACbnR,KAAAsY,mBAAqB,IAAIuE,qBAAmB,CAC/CtP,aACAlN,SAAU,WAKPL,KAAKsY,kBAAA,CAOd,qBAAAtD,GACE,OAAOhV,KAAKsY,kBAAA,CAOd,eAAA5L,CAAgBD,GACdzM,KAAKsS,aAAe7F,EACpBzM,KAAKyc,4BAA8B,CAAC,EAGhCzc,KAAKsY,oBACPtY,KAAKsY,mBAAmBwE,UAC1B,CAMF,eAAAvK,GACE,OAAOvS,KAAKsS,YAAA,CAQd,mBAAAP,CAAoBS,GACd,IAACxS,KAAKsY,mBAIR,MAHAtY,KAAKW,OAAOgB,MACV,oGAEI,IAAIR,MACR,oGAKJ,MAAM4b,EAA4B,CAChCrL,kBAAmBc,EAAWd,kBAC9BE,gBAAiBY,EAAWZ,gBAC5BC,gBAAiBW,EAAWX,gBAC5BC,qBAAsBU,EAAWV,qBACjCmC,OAAQjU,KAAKgd,wBAAwBxK,EAAWyB,QAAU,eAC1DE,UAAW3B,EAAW2B,YAAa,EACnCC,kBAAmB5B,EAAW4B,oBAAqB,EACnDpO,QAASwM,EAAWxM,SAAW,IAAI+H,KACnC+G,aAActC,EAAWsC,aACzBL,YAAajC,EAAWiC,YACxBhT,oBAAqB+Q,EAAW/Q,oBAChCwb,WAAW,GAIRjd,KAAAsY,mBAAmBpD,sBAAsB6H,GAGzC/c,KAAAkd,4BAA4B1K,EAAWd,kBAAiB,CAO/D,qBAAAwD,CAAsB1C,GACpBxS,KAAK+R,oBAAoBS,EAAU,CAMrC,eAAAa,GACM,OAACrT,KAAKsY,mBAQHtY,KAAKsY,mBACT6E,oBACAtX,KAAKyO,GAAStU,KAAKod,0BAA0B9I,MAT9CtU,KAAKW,OAAOwQ,MACV,wEAEK,GAM4C,CASvD,yBAAAsB,CAA0B4K,GACpB,IAACrd,KAAKsY,mBACD,OAGH,MAAAlF,EAAcpT,KAAKqT,kBAGnBiK,EAAeC,SAASF,GAAc,EAE1C,IAACtK,MAAMuK,IACPA,GAAgB,GAChBA,EAAelK,EAAY7H,OAE3B,OAAO6H,EAAYkK,GAIrB,MAAME,EACJxd,KAAKsY,mBAAmBmF,uBAAuBJ,GACjD,GAAIG,EACK,OAAAxd,KAAKod,0BAA0BI,GAIxC,MAAME,EACJ1d,KAAKsY,mBAAmBqF,yBAAyBN,GACnD,OAAIK,EACK1d,KAAKod,0BAA0BM,QADxC,CAIO,CAOT,gBAAAjI,CAAiB/D,GACR,OAAA1R,KAAKyc,4BAA4B/K,IAAsB,CAAA,CAOhE,eAAA4E,CAAgB5E,EAA2BkM,GAErC,KAAElM,KAAqB1R,KAAKyc,6BAE9B,YADKzc,KAAAyc,4BAA4B/K,GAAqBkM,GAOpDA,EADF5d,KAAKyc,4BAA4B/K,KAE5B1R,KAAAyc,4BAA4B/K,GAAqBkM,EACxD,CAOM,2BAAAV,CAA4BxL,GAC5BA,KAAqB1R,KAAKyc,8BAC9Bzc,KAAKyc,4BAA4B/K,GAClB,IAAb3D,KAAKyJ,MACT,CAMM,uBAAAwF,CACN/I,GAEA,OAAQA,GACN,IAAK,UACI,MAAA,UACT,IAAK,cAIL,QACS,MAAA,cAHT,IAAK,qBACI,MAAA,qBAGX,CAMM,yBAAAmJ,CAA0B9I,GACzB,MAAA,CACL1C,gBAAiB0C,EAAK1C,gBACtBC,gBAAiByC,EAAKzC,iBAAmB,SAASyC,EAAK1C,kBACvDE,qBAAsBwC,EAAKxC,sBAAwB,GACnDJ,kBAAmB4C,EAAK5C,kBACxBuC,OAAQjU,KAAK6d,qBAAqBvJ,EAAKL,QACvCjO,QAASsO,EAAKtO,QACd8O,aAAcR,EAAKQ,aACnBX,UAAWG,EAAKH,UAChBC,kBAAmBE,EAAKF,kBACxBK,YAAaH,EAAKG,YAClBhT,oBAAqB6S,EAAK7S,oBAC5B,CAMM,oBAAAoc,CAAqB5J,GAC3B,OAAQA,GACN,IAAK,UACI,MAAA,UACT,IAAK,cAIL,IAAK,SACI,MAAA,cAHT,IAAK,qBACI,MAAA,qBAGT,QACS,MAAA,UACX,CAQF,sBAAMtH,CACJF,EACA1M,GAEA,GAAIA,GAASqD,MAAyB,aAAjBrD,EAAQqD,KAC3B,MAAM,IAAIjC,MACR,iCAAiCpB,EAAQqD,uCAI7C,MAAM0a,EACH/d,GAAuC+d,aACxC9d,KAAK0c,oBACLlc,QAAQC,IAAI6b,eACZ,OAQI3S,EACH5J,GAAuC4J,QAAU3J,KAAK2c,cAErD,IAAClQ,EAAM1K,YAAc0K,EAAMlL,iBAAmBkL,EAAMrK,gBAChD,MAAA,IAAIjB,MAAM,wDAGlB,MAAM4c,EAAkC,CACtC,CAAC,GAAGpU,gBAAsB8C,EAAM1K,UAChC,CAAC,GAAG4H,sBAA4B8C,EAAMlL,eACtC,CAAC,GAAGoI,uBAA6B8C,EAAMrK,iBAGrCqK,EAAMnF,aACRyW,EAAQ,GAAGpU,iBAAwB8C,EAAMnF,YAGvCmF,EAAMH,iBACRyR,EAAQ,GAAGpU,sBAA6B8C,EAAMH,sBD/M9BgB,eACpBwQ,EACAE,GAEA,IAAIC,EAAa,GAEbtT,EAAGC,WAAWkT,KACHG,EAAAtT,EAAGE,aAAaiT,EAAa,SAGtC,MACAI,EAAe,IADJD,EAAW3M,MAAM,OAGlC,IAAA,MAAY3M,EAAKC,KAAUR,OAAOC,QAAQ2Z,GAAY,CACpD,MAAMG,EAAYD,EAAaE,WAAWC,GACxCA,EAAKvU,WAAW,GAAGnF,SAGC,IAAlBwZ,EACFD,EAAaC,GAAa,GAAGxZ,KAAOC,IAEpCsZ,EAAahF,KAAK,GAAGvU,KAAOC,IAC9B,CAGF+F,EAAG2T,cAAcR,EAAaI,EAAa9O,KAAK,MAClD,CCwLUmP,CAAcT,EAAaC,EAAO,ECjVrC,MAAeS,EAapB,gBAAMC,CAAWC,GACf1e,KAAK0e,QAAUA,CAAA,CAajB,aAAMC,GAAyB,EC5BjC,MAKMC,EAA6B1W,IAAEC,OAAO,CAC1C0W,aAAc3W,IAAEC,OAAO,CACrB2W,gBAAiB5W,IAAEO,SACnBsW,gBAAiB7W,IAAEO,SACnBuW,gBAAiB9W,IAAEO,WAErBwW,UAAW/W,IAAEC,OAAO,CAClB2W,gBAAiB5W,IAAEO,SACnBsW,gBAAiB7W,IAAEO,SACnBuW,gBAAiB9W,IAAEO,WAErB1C,UAAWmC,IAAEE,WAOR,MAAM8W,UAAyBpX,EAAAA,eAA/B,WAAAnI,GAAAqI,SAAAmX,WACEnf,KAAA4C,KAAA,eACO5C,KAAA8C,YAAA,0EACL9C,KAAAiI,OAAAC,IAAEC,OAAO,CAAA,EAAE,CAQpB,WAAgB2C,GACV,IAEF,MAGMzF,SAHiB2E,EAAMC,IAAI,sEAGF5E,KAGzB+Z,EAAaR,EAA2BS,UAAUha,GACpD,IAAC+Z,EAAWzY,QAEP,MADEwO,QAAAxT,MAAM,0CAA2Cyd,EAAWzd,OAC9D,IAAIR,MAAM,+BAGb,MAAA0d,aAAEA,GAAiBO,EAAW/Z,KAGpC,MAAO,kCAFUwZ,EAAaC,gBAAkBD,EAAaE,gBAAkB,KAE9B9Q,QAAQ,gBAClDtM,GACCwT,QAAAxT,MAAM,6BAA8BA,GAE5C,IAAI6Z,EAAe,4BASnB,OARIxR,EAAMsV,aAAa3d,IACrB6Z,EAAe7Z,EAAMC,QACjBD,EAAMoI,WACQyR,GAAA,aAAa7Z,EAAMoI,SAASkK,YAErCtS,aAAiBR,QAC1Bqa,EAAe7Z,EAAMC,SAEhB,kCAAkC4Z,GAAY,CACvD,EChEG,MAAe+D,UAAsBf,gRCArC,cAAmCA,4BF0EnC,MASL,WAAA7e,GARKK,KAAA6L,GAAA,oBACE7L,KAAA4C,KAAA,2BACO5C,KAAA8C,YAAA,gFACJ9C,KAAAwf,QAAA,QACDxf,KAAAyf,OAAA,eAKPzf,KAAK0f,MAAQ,CAAC,IAAIR,EAAkB,CAMtC,gBAAMT,GAEJ,OAAO1O,QAAQC,SAAQ,CAOzB,QAAA2P,GACE,OAAO3f,KAAK0f,KAAA,CAMd,aAAMf,GAEJ,OAAO5O,QAAQC,SAAQ,iLGzFpB,cAA+BuP,EAA/B,WAAA5f,GAAAqI,SAAAmX,WACAnf,KAAA6L,GAAA,iCACE7L,KAAA4C,KAAA,wCAEL5C,KAAA8C,YAAA,qGACQ9C,KAAAwf,QAAA,QACDxf,KAAAyf,OAAA,mBACGzf,KAAA4f,UAAA,aAIZ5f,KAAQ0f,MAA0B,EAAC,CAEnC,gBAAejB,CAAWC,GAGpB,SAFE1W,MAAMyW,WAAWC,KAEjBA,EAAQ3W,kBAAkBrI,GACxB,MAAA,IAAIyB,MAAM,qDAGlBnB,KAAK6f,YAAcnB,EAAQ3W,OAE3B/H,KAAK2H,aACF+W,EAAQ/W,cAAkC,IAAI6U,EAEjDxc,KAAK8f,kBAEL9f,KAAK0e,QAAQ/d,OAAOsD,KAClB,iEACF,CAGM,eAAA6b,GACN,IAAK9f,KAAK6f,cAAgB7f,KAAK2H,aAC7B,MAAM,IAAIxG,MACR,0EAIJnB,KAAK0f,MAAQ,CACX,IAAI7X,EAAkB7H,KAAK6f,YAAa7f,KAAK2H,cAC7C,IAAI2H,EAAgBtP,KAAK6f,aACzB,IAAI3P,EAAe,CACjBnI,OAAQ/H,KAAK6f,YACblY,aAAc3H,KAAK2H,eAErB,IAAI4O,EAAsB,CACxBpE,UAAWnS,KAAK6f,cAElB,IAAIvE,EAAoBtb,KAAK6f,aAC7B,IAAIlN,EAAuB,CACzBR,UAAWnS,KAAK6f,YAChBlY,aAAc3H,KAAK2H,eAErB,IAAIgM,EAAoB,CACtBxB,UAAWnS,KAAK6f,YAChBlY,aAAc3H,KAAK2H,eAErB,IAAIuK,EAA4B,CAC9BC,UAAWnS,KAAK6f,YAChBlY,aAAc3H,KAAK2H,eAErB,IAAIyN,EAAkB,CACpBjD,UAAWnS,KAAK6f,YAChBlY,aAAc3H,KAAK2H,eAErB,IAAIoP,EAAsB,CACxB5E,UAAWnS,KAAK6f,YAChBlY,aAAc3H,KAAK2H,eAErB,IAAI+R,EAA6B,CAC/BvH,UAAWnS,KAAK6f,YAChBlY,aAAc3H,KAAK2H,eAErB,IAAIoT,EAA4B,CAC9B5I,UAAWnS,KAAK6f,YAChBlY,aAAc3H,KAAK2H,eAErB,IAAI8T,EAAqC,CACvC9T,aAAc3H,KAAK2H,aACnBwK,UAAWnS,KAAK6f,cAEpB,CAGF,QAAAF,GACE,OAAO3f,KAAK0f,KAAA,CAGd,aAAef,GACb3e,KAAK0f,MAAQ,GACb1f,KAAK6f,iBAAc,EACnB7f,KAAK2H,kBAAe,EACpB3H,KAAK0e,QAAQ/d,OAAOsD,KAClB,mDACF,kDCtGG,MAQL,8BAAa8b,CACXC,EACAtB,EACA3e,EAA6B,CAAE0e,YAAY,IAE3C,MAAMwB,EAAenX,EAAKsG,KAAK4Q,EAAW,eAE1C,IAAKrV,EAAGC,WAAWqV,GACjB,MAAM,IAAI9e,MAAM,gCAAgC8e,KAG9C,IACF,MAAMC,EAAkBvV,EAAGE,aAAaoV,EAAc,QAChDE,EAAWhT,KAAK2C,MAAMoQ,GAG5B,IAAKC,EAAStU,KAAOsU,EAASC,KACtB,MAAA,IAAIjf,MAAM,+DAIlB,MAAMkf,EAAWvX,EAAKsG,KAAK4Q,EAAWG,EAASC,MAC/C,IAAKzV,EAAGC,WAAWyV,GACjB,MAAM,IAAIlf,MAAM,iCAAiCkf,KAI7C,MAAAC,QAAqBC,OAAOF,GAC5BG,EAAcF,EAAajO,SAAWiO,EAAaH,EAAStU,IAElE,IAAK2U,EACH,MAAM,IAAIrf,MAAM,kCAAkCkf,KAI9C,MAAAI,EAAS,IAAID,EAGnB,IAAKxgB,KAAK0gB,cAAcD,GAChB,MAAA,IAAItf,MAAM,6DAQX,OAJHpB,EAAQ0e,kBACJgC,EAAOhC,WAAWC,GAGnB+B,QACA9e,GACP,MAAM,IAAIR,MAAM,wCAAwC6e,MAAcre,aAAiBR,MAAQQ,EAAMC,QAAUC,OAAOF,KAAQ,CAChI,CAUF,4BAAagf,CACXC,EACAlC,EACA3e,EAA6B,CAAE0e,YAAY,IAEvC,IAEI,MAAAoC,EAAcC,QAAQ9Q,QAAQ4Q,GAC9BG,EAAajY,EAAKkY,QAAQH,GAEhC,OAAO7gB,KAAK+f,kBAAkBgB,EAAYrC,EAAS3e,SAC5C4B,GACP,MAAM,IAAIR,MAAM,sCAAsCyf,MAAgBjf,aAAiBR,MAAQQ,EAAMC,QAAUC,OAAOF,KAAQ,CAChI,CAQF,oBAAe+e,CAAcO,GAEzB,OAAAA,GACkB,iBAAXA,EAAIpV,IACS,iBAAboV,EAAIre,MACgB,iBAApBqe,EAAIne,aACY,iBAAhBme,EAAIzB,SACW,iBAAfyB,EAAIxB,QACe,mBAAnBwB,EAAIxC,YACa,mBAAjBwC,EAAItB,QAAa,0BC9GvB,MASL,WAAAhgB,CAAY+e,GARJ1e,KAAAkhB,YAAoCjJ,IAS1CjY,KAAK0e,QAAUA,EACf1e,KAAKW,OAAS+d,EAAQ/d,MAAA,CAQxB,oBAAMwgB,CAAeV,GACnB,GAAIzgB,KAAKkhB,QAAQ3P,IAAIkP,EAAO5U,IAC1B,MAAM,IAAI1K,MAAM,kBAAkBsf,EAAO5U,kCAGrC4U,EAAOhC,WAAWze,KAAK0e,SAC7B1e,KAAKkhB,QAAQhJ,IAAIuI,EAAO5U,GAAI4U,GACvBzgB,KAAAW,OAAOsD,KAAK,sBAAsBwc,EAAO7d,SAAS6d,EAAO5U,QAAQ4U,EAAOjB,UAAS,CAQxF,SAAA4B,CAAUvV,GACD,OAAA7L,KAAKkhB,QAAQjX,IAAI4B,EAAE,CAO5B,aAAAwV,GACE,OAAOC,MAAMhX,KAAKtK,KAAKkhB,QAAQK,SAAQ,CAOzC,WAAAC,GACS,OAAAxhB,KAAKqhB,gBAAgBI,SAAkBhB,GAAAA,EAAOd,YAAU,CAQjE,sBAAM+B,CAAiB7V,GACrB,MAAM4U,EAASzgB,KAAKkhB,QAAQjX,IAAI4B,GAChC,IAAK4U,EACI,OAAA,EAGT,GAAIA,EAAO9B,QACL,UACI8B,EAAO9B,gBACNhd,GACP3B,KAAKW,OAAOgB,MAAM,gCAAgCA,IAAO,CAI7D,MAAMqD,EAAShF,KAAKkhB,QAAQS,OAAO9V,GAK5B,OAJH7G,GACGhF,KAAAW,OAAOsD,KAAK,wBAAwBwc,EAAO7d,SAAS6d,EAAO5U,OAG3D7G,CAAA,CAMT,0BAAM4c,GACJ,MAAMC,EAAYP,MAAMhX,KAAKtK,KAAKkhB,QAAQY,QAC1C,IAAA,MAAWjW,KAAMgW,QACT7hB,KAAK0hB,iBAAiB7V,EAC9B,iKClCF9L,IAOM,MAAAgiB,EAAShiB,GAASiiB,cAAgB,CAAC,EAEnCpiB,EAAamiB,EAAOniB,YAAcY,QAAQC,IAAIwhB,mBAC9CpiB,EACJkiB,EAAOG,aAAe1hB,QAAQC,IAAI0hB,oBAE9BC,EAAaL,EAAOjiB,SAAWU,QAAQC,IAAI4hB,gBAAkB,UAE/D,IAAAviB,EAYA,GAXe,YAAfsiB,EACQtiB,EAAA,WACc,YAAfsiB,GAGDjN,QAAAnR,KACN,mCAAmCoe,gCAH3BtiB,EAAA,YAQPF,IAAeC,EAClB,MAAM,IAAIsB,MACR,iGAIE,MAAAZ,EAAgD,SAAhCC,QAAQC,IAAIC,gBAC5BC,EAASC,SAAOiJ,YAAY,CAChChJ,MAAOkhB,EAAO1hB,UAAY,OAC1BS,OAAQP,IAGJoH,EACJ5H,GAAS4H,cACT,IAAI6U,EAAgB,CAClBE,mBAAoBJ,EACpBK,cAAe,SAEnBhc,EAAOsD,KAAK,6BAEZ,MAAM4b,EAAc,IAAIngB,EAAYE,EAAYC,EAAoBC,EAAS,CAC3EQ,cAAeyhB,EAAOzhB,cACtBF,YAAa2hB,EAAO3hB,cAIlB,IAAAkiB,EAFJ3hB,EAAOsD,KAAK,+BAA+BrE,QAAiBE,KAGxDC,GAASuiB,mBACXA,EAAmB,IAAI5iB,EACrBE,EACAC,EACAC,EACA,CACEQ,cAAeyhB,EAAOzhB,cACtBF,YAAa2hB,EAAO3hB,YACpBC,SAAU,UAGdM,EAAOsD,KAAK,kCAGd,MAAMyb,EAA6B,CAAC,EAmD7B,OAjDPA,EAAM6C,kBAAoB,IAAI1a,EAAkBgY,EAAalY,GACvD+X,EAAA8C,gBAAkB,IAAIlT,EAAgBuQ,GACtCH,EAAA+C,eAAiB,IAAIvS,EAAe,CACxCnI,OAAQua,GAAoBzC,EAC5BlY,iBAGE5H,GAAS2iB,iBACLhD,EAAAiD,sBAAwB,IAAIpM,EAAsB,CACtDpE,UAAW0N,IAEPH,EAAAkD,oBAAsB,IAAItH,EAAoBuE,GAC9CH,EAAAmD,uBAAyB,IAAIlQ,EAAuB,CACxDR,UAAW0N,EACXlY,iBAEI+X,EAAAvI,oBAAsB,IAAIxD,EAAoB,CAClDxB,UAAW0N,EACXlY,iBAEI+X,EAAAoD,4BAA8B,IAAI5Q,EAA4B,CAClEC,UAAW0N,EACXlY,iBAEI+X,EAAAqD,kBAAoB,IAAI3N,EAAkB,CAC9CjD,UAAW0N,EACXlY,iBAEI+X,EAAAsD,sBAAwB,IAAIjM,EAAsB,CACtD5E,UAAWmQ,GAAoBzC,EAC/BlY,iBAEI+X,EAAAuD,6BAA+B,IAAIvJ,EAA6B,CACpEvH,UAAW0N,EACXlY,iBAEI+X,EAAAwD,4BAA8B,IAAInI,EAA4B,CAClE5I,UAAW0N,EACXlY,iBAEI+X,EAAAyD,qCACJ,IAAI1H,EAAqC,CACvC9T,eACAwK,UAAW0N,IAGflf,EAAOsD,KAAK,0BAGP,CACL4b,cACAyC,mBACA5C,MAAAA,EACA/X"}
|