UNPKG

@hashgraphonline/conversational-agent

Version:

Hashgraph Online conversational AI agent implementing HCS-10 communication, HCS-2 registries, and content inscription on Hedera. https://hol.org

252 lines (226 loc) 7.5 kB
import { GenericPluginContext, HederaTool, BasePlugin, HederaAgentKit, } from 'hedera-agent-kit'; import { IStateManager, OpenConvaiState, HCS10Builder, RegisterAgentTool, FindRegistrationsTool, InitiateConnectionTool, ListConnectionsTool, SendMessageToConnectionTool, CheckMessagesTool, ConnectionMonitorTool, ManageConnectionRequestsTool, AcceptConnectionRequestTool, RetrieveProfileTool, ListUnapprovedConnectionRequestsTool, RegisteredAgent, } from '@hashgraphonline/standards-agent-kit'; import { HCS10Client } from '@hashgraphonline/standards-sdk'; import { PrivateKey } from 'node_modules/@hashgraph/sdk/lib/Mnemonic'; interface HCS10ClientManager { initializeConnectionsManager(client: HCS10Client): void; } function hasInitializeConnectionsManager( stateManager: IStateManager ): stateManager is IStateManager & HCS10ClientManager { return ( typeof stateManager === 'object' && stateManager !== null && 'initializeConnectionsManager' in stateManager && typeof stateManager.initializeConnectionsManager === 'function' ); } export class HCS10Plugin extends BasePlugin { id = 'hcs-10'; name = 'HCS-10 Plugin'; description = 'HCS-10 agent tools for decentralized agent registration, connections, and messaging on Hedera'; version = '1.0.0'; author = 'Hashgraph Online'; namespace = 'hcs10'; private stateManager?: IStateManager; private tools: any[] = []; appConfig?: Record<string, unknown>; override async initialize(context: GenericPluginContext): Promise<void> { await super.initialize(context); const hederaKit = context.config.hederaKit as HederaAgentKit; if (!hederaKit) { this.context.logger.warn( 'HederaKit not found in context. HCS-10 tools will not be available.' ); return; } try { this.stateManager = (context.stateManager as IStateManager) || (context.config.stateManager as IStateManager) || (this.appConfig?.stateManager as IStateManager) || new OpenConvaiState(); const accountId = hederaKit.signer.getAccountId().toString(); const isBytesMode = String(hederaKit.operationalMode || 'returnBytes') === 'returnBytes'; let inboundTopicId = ''; let outboundTopicId = ''; let operatorPrivateKeyRef: PrivateKey = hederaKit.signer.getOperatorPrivateKey(); let operatorPrivateKeySerialized: string | undefined; try { const resolved = typeof operatorPrivateKeyRef?.toString === 'function' ? operatorPrivateKeyRef.toString() : ''; operatorPrivateKeySerialized = resolved; const hcs10Client = new HCS10Client({ network: hederaKit.network as 'mainnet' | 'testnet', operatorId: accountId, operatorPrivateKey: operatorPrivateKeyRef, logLevel: 'error', }); const profileResponse = await hcs10Client.retrieveProfile(accountId); if (profileResponse.success && profileResponse.topicInfo) { inboundTopicId = profileResponse.topicInfo.inboundTopic; outboundTopicId = profileResponse.topicInfo.outboundTopic; } } catch (profileError) { this.context.logger.warn( 'Skipping profile topic discovery', profileError ); } const agentRecord: Record<string, unknown> = { name: `Agent ${accountId}`, accountId: accountId, inboundTopicId, outboundTopicId, }; if (!isBytesMode && operatorPrivateKeySerialized) { agentRecord.privateKey = operatorPrivateKeySerialized; } this.stateManager.setCurrentAgent( agentRecord as unknown as RegisteredAgent ); this.context.logger.info( `Set current agent: ${accountId} with topics ${inboundTopicId}/${outboundTopicId}` ); if ( !isBytesMode && this.stateManager && !this.stateManager.getConnectionsManager() ) { try { const hcs10Client = new HCS10Client({ network: hederaKit.network as 'mainnet' | 'testnet', operatorId: accountId, operatorPrivateKey: operatorPrivateKeyRef ?? '', logLevel: 'error', }); if (hasInitializeConnectionsManager(this.stateManager)) { this.stateManager.initializeConnectionsManager(hcs10Client); } else { this.context.logger.warn( 'StateManager does not support connection manager initialization' ); } this.context.logger.info( 'ConnectionsManager initialized in HCS10Plugin' ); } catch (cmError) { this.context.logger.warn( 'Could not initialize ConnectionsManager:', cmError ); } } this.initializeTools(); this.context.logger.info('HCS-10 Plugin initialized successfully'); } catch (error) { this.context.logger.error('Failed to initialize HCS-10 plugin:', error); } } private initializeTools(): void { if (!this.stateManager) { throw new Error('StateManager must be initialized before creating tools'); } const hederaKit = this.context.config.hederaKit as HederaAgentKit; if (!hederaKit) { throw new Error('HederaKit not found in context config'); } const hcs10Builder = new HCS10Builder(hederaKit, this.stateManager); this.tools = [ new RegisterAgentTool({ hederaKit: hederaKit, hcs10Builder: hcs10Builder, logger: this.context.logger, }), new FindRegistrationsTool({ hederaKit: hederaKit, hcs10Builder: hcs10Builder, logger: this.context.logger, }), new RetrieveProfileTool({ hederaKit: hederaKit, hcs10Builder: hcs10Builder, logger: this.context.logger, }), new InitiateConnectionTool({ hederaKit: hederaKit, hcs10Builder: hcs10Builder, logger: this.context.logger, }), new ListConnectionsTool({ hederaKit: hederaKit, hcs10Builder: hcs10Builder, logger: this.context.logger, }), new SendMessageToConnectionTool({ hederaKit: hederaKit, hcs10Builder: hcs10Builder, logger: this.context.logger, }), new CheckMessagesTool({ hederaKit: hederaKit, hcs10Builder: hcs10Builder, logger: this.context.logger, }), new ConnectionMonitorTool({ hederaKit: hederaKit, hcs10Builder: hcs10Builder, logger: this.context.logger, }), new ManageConnectionRequestsTool({ hederaKit: hederaKit, hcs10Builder: hcs10Builder, logger: this.context.logger, }), new AcceptConnectionRequestTool({ hederaKit: hederaKit, hcs10Builder: hcs10Builder, logger: this.context.logger, }), new ListUnapprovedConnectionRequestsTool({ hederaKit: hederaKit, hcs10Builder: hcs10Builder, logger: this.context.logger, }), ]; } getTools(): HederaTool[] { return this.tools; } getStateManager(): IStateManager | undefined { return this.stateManager; } override async cleanup(): Promise<void> { this.tools = []; delete this.stateManager; if (this.context?.logger) { this.context.logger.info('HCS-10 Plugin cleaned up'); } } }