@hashgraphonline/conversational-agent 0.0.3 → 0.1.0
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/README.md +79 -0
- package/dist/cjs/agent-factory.d.ts +5 -0
- package/dist/cjs/base-agent.d.ts +95 -0
- package/dist/cjs/conversational-agent.d.ts +62 -5
- package/dist/cjs/index.cjs +1 -1
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.ts +8 -0
- package/dist/cjs/langchain-agent.d.ts +22 -0
- package/dist/cjs/mcp/MCPClientManager.d.ts +40 -0
- package/dist/cjs/mcp/adapters/langchain.d.ts +8 -0
- package/dist/cjs/mcp/helpers.d.ts +45 -0
- package/dist/cjs/mcp/types.d.ts +27 -0
- package/dist/cjs/plugins/hbar-transfer/AccountBuilder.d.ts +13 -0
- package/dist/cjs/plugins/hbar-transfer/HbarTransferPlugin.d.ts +15 -0
- package/dist/cjs/plugins/hbar-transfer/TransferHbarTool.d.ts +61 -0
- package/dist/cjs/plugins/hbar-transfer/index.d.ts +1 -0
- package/dist/cjs/plugins/hbar-transfer/types.d.ts +10 -0
- package/dist/cjs/plugins/index.d.ts +1 -0
- package/dist/cjs/providers.d.ts +48 -0
- package/dist/esm/index.js +18 -3
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/index10.js +22 -0
- package/dist/esm/index10.js.map +1 -0
- package/dist/esm/index11.js +104 -0
- package/dist/esm/index11.js.map +1 -0
- package/dist/esm/index12.js +36 -0
- package/dist/esm/index12.js.map +1 -0
- package/dist/esm/index13.js +16 -0
- package/dist/esm/index13.js.map +1 -0
- package/dist/esm/index14.js +127 -0
- package/dist/esm/index14.js.map +1 -0
- package/dist/esm/index15.js +132 -0
- package/dist/esm/index15.js.map +1 -0
- package/dist/esm/index16.js +95 -0
- package/dist/esm/index16.js.map +1 -0
- package/dist/esm/index5.js +42 -202
- package/dist/esm/index5.js.map +1 -1
- package/dist/esm/index6.js +295 -13
- package/dist/esm/index6.js.map +1 -1
- package/dist/esm/index7.js +87 -0
- package/dist/esm/index7.js.map +1 -0
- package/dist/esm/index8.js +255 -0
- package/dist/esm/index8.js.map +1 -0
- package/dist/esm/index9.js +18 -0
- package/dist/esm/index9.js.map +1 -0
- package/dist/types/agent-factory.d.ts +5 -0
- package/dist/types/base-agent.d.ts +95 -0
- package/dist/types/conversational-agent.d.ts +62 -5
- package/dist/types/index.d.ts +8 -0
- package/dist/types/langchain-agent.d.ts +22 -0
- package/dist/types/mcp/MCPClientManager.d.ts +40 -0
- package/dist/types/mcp/adapters/langchain.d.ts +8 -0
- package/dist/types/mcp/helpers.d.ts +45 -0
- package/dist/types/mcp/types.d.ts +27 -0
- package/dist/types/plugins/hbar-transfer/AccountBuilder.d.ts +13 -0
- package/dist/types/plugins/hbar-transfer/HbarTransferPlugin.d.ts +15 -0
- package/dist/types/plugins/hbar-transfer/TransferHbarTool.d.ts +61 -0
- package/dist/types/plugins/hbar-transfer/index.d.ts +1 -0
- package/dist/types/plugins/hbar-transfer/types.d.ts +10 -0
- package/dist/types/plugins/index.d.ts +1 -0
- package/dist/types/providers.d.ts +48 -0
- package/package.json +12 -6
- package/src/agent-factory.ts +21 -0
- package/src/base-agent.ts +222 -0
- package/src/conversational-agent.ts +204 -102
- package/src/index.ts +24 -0
- package/src/langchain-agent.ts +333 -0
- package/src/mcp/MCPClientManager.ts +148 -0
- package/src/mcp/adapters/langchain.ts +185 -0
- package/src/mcp/helpers.ts +122 -0
- package/src/mcp/types.ts +29 -0
- package/src/plugins/hbar-transfer/AccountBuilder.ts +154 -0
- package/src/plugins/hbar-transfer/HbarTransferPlugin.ts +66 -0
- package/src/plugins/hbar-transfer/TransferHbarTool.ts +49 -0
- package/src/plugins/hbar-transfer/index.ts +1 -0
- package/src/plugins/hbar-transfer/types.ts +11 -0
- package/src/plugins/index.ts +2 -1
- package/src/providers.ts +82 -0
package/README.md
CHANGED
|
@@ -137,6 +137,7 @@ When using `returnBytes` mode:
|
|
|
137
137
|
- **TypeScript Support**: Full type definitions for all components
|
|
138
138
|
- **State Management**: Integrated state management for agent operations
|
|
139
139
|
- **CLI Interface**: Beautiful terminal interface for interactive agent communication
|
|
140
|
+
- **MCP Support**: Extend agent capabilities with Model Context Protocol servers
|
|
140
141
|
|
|
141
142
|
## Available Tools
|
|
142
143
|
|
|
@@ -469,8 +470,86 @@ const agent = new HederaConversationalAgent(signer, {
|
|
|
469
470
|
- [Conversational Agent Documentation](https://hashgraphonline.com/docs/libraries/conversational-agent/)
|
|
470
471
|
- [Standards Agent Kit Documentation](https://hashgraphonline.com/docs/libraries/standards-agent-kit/)
|
|
471
472
|
- [HCS Standards Documentation](https://hcs-improvement-proposals.pages.dev/docs/standards)
|
|
473
|
+
- [MCP Integration Guide](./docs/MCP_INTEGRATION.md)
|
|
472
474
|
- [GitHub Repository](https://github.com/hashgraph-online/conversational-agent)
|
|
473
475
|
|
|
476
|
+
## Contributing
|
|
477
|
+
|
|
478
|
+
We welcome contributions from the community! Whether you're fixing bugs, adding features, or creating new plugins, your contributions help make the Conversational Agent better for everyone.
|
|
479
|
+
|
|
480
|
+
### Contributing a Plugin
|
|
481
|
+
|
|
482
|
+
If you've created a plugin that extends the Conversational Agent's capabilities, we'd love to include it in the repository. Here's how:
|
|
483
|
+
|
|
484
|
+
1. **Fork the Repository**
|
|
485
|
+
```bash
|
|
486
|
+
git clone https://github.com/hashgraph-online/conversational-agent.git
|
|
487
|
+
cd conversational-agent
|
|
488
|
+
pnpm install
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
2. **Create Your Plugin**
|
|
492
|
+
- Place your plugin in `src/plugins/community/[your-plugin-name]/`
|
|
493
|
+
- Follow the plugin structure outlined in the [Plugin Development Guide](docs/PLUGIN_DEVELOPMENT.md)
|
|
494
|
+
- Include comprehensive tests in `src/plugins/community/[your-plugin-name]/__tests__/`
|
|
495
|
+
- Add documentation in `src/plugins/community/[your-plugin-name]/README.md`
|
|
496
|
+
|
|
497
|
+
3. **Plugin Requirements**
|
|
498
|
+
- Must extend `BasePlugin` from hedera-agent-kit
|
|
499
|
+
- Include clear tool descriptions for AI understanding
|
|
500
|
+
- Add proper error handling and validation
|
|
501
|
+
- Follow TypeScript best practices
|
|
502
|
+
- Include unit tests with >80% coverage
|
|
503
|
+
- Document all configuration options
|
|
504
|
+
- Add usage examples
|
|
505
|
+
|
|
506
|
+
4. **Submit a Pull Request**
|
|
507
|
+
- Create a feature branch: `git checkout -b feature/add-[plugin-name]-plugin`
|
|
508
|
+
- Commit your changes with clear messages
|
|
509
|
+
- Push to your fork and create a PR
|
|
510
|
+
- Include a description of what your plugin does and why it's useful
|
|
511
|
+
- Link to any relevant HCS standards or documentation
|
|
512
|
+
|
|
513
|
+
### Plugin Review Process
|
|
514
|
+
|
|
515
|
+
1. **Code Review**: Maintainers will review your code for quality, security, and adherence to standards
|
|
516
|
+
2. **Testing**: All tests must pass, and the plugin must work with the latest agent version
|
|
517
|
+
3. **Documentation**: Clear documentation and examples are required
|
|
518
|
+
4. **Integration**: Once approved, your plugin will be added to the community plugins directory
|
|
519
|
+
|
|
520
|
+
### Example Plugin Structure
|
|
521
|
+
|
|
522
|
+
```
|
|
523
|
+
src/plugins/community/your-plugin/
|
|
524
|
+
├── index.ts # Main plugin export
|
|
525
|
+
├── YourPlugin.ts # Plugin implementation
|
|
526
|
+
├── tools/ # Tool implementations
|
|
527
|
+
│ ├── YourTool1.ts
|
|
528
|
+
│ └── YourTool2.ts
|
|
529
|
+
├── __tests__/ # Test files
|
|
530
|
+
│ ├── YourPlugin.test.ts
|
|
531
|
+
│ └── tools/
|
|
532
|
+
│ ├── YourTool1.test.ts
|
|
533
|
+
│ └── YourTool2.test.ts
|
|
534
|
+
├── README.md # Plugin documentation
|
|
535
|
+
└── package.json # Plugin metadata (optional)
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
### General Contribution Guidelines
|
|
539
|
+
|
|
540
|
+
- **Code Style**: Follow the existing code style and linting rules
|
|
541
|
+
- **Commits**: Use clear, descriptive commit messages
|
|
542
|
+
- **Documentation**: Update relevant documentation for any changes
|
|
543
|
+
- **Tests**: Add tests for new functionality
|
|
544
|
+
- **Issues**: Open an issue before working on major changes
|
|
545
|
+
|
|
546
|
+
### Getting Help
|
|
547
|
+
|
|
548
|
+
- Join our [Discord community](https://discord.gg/hashgraphonline) for discussions
|
|
549
|
+
- Check existing issues and PRs before starting work
|
|
550
|
+
- Ask questions in the #development channel
|
|
551
|
+
- Review the [HCS Standards](https://hcs-improvement-proposals.pages.dev/docs/standards) for protocol details
|
|
552
|
+
|
|
474
553
|
## License
|
|
475
554
|
|
|
476
555
|
Apache-2.0
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { BaseMessage } from '@langchain/core/messages';
|
|
2
|
+
import { StructuredTool } from '@langchain/core/tools';
|
|
3
|
+
import { TransactionReceipt } from '@hashgraph/sdk';
|
|
4
|
+
import { HederaAgentKit, ServerSigner, TokenUsageCallbackHandler, TokenUsage, BasePlugin, CostCalculation } from 'hedera-agent-kit';
|
|
5
|
+
import { AIProvider, VercelAIProvider, BAMLProvider } from './providers';
|
|
6
|
+
import { Logger } from '@hashgraphonline/standards-sdk';
|
|
7
|
+
import { MCPServerConfig } from './mcp/types';
|
|
8
|
+
|
|
9
|
+
export interface ToolFilterConfig {
|
|
10
|
+
namespaceWhitelist?: string[];
|
|
11
|
+
toolBlacklist?: string[];
|
|
12
|
+
toolPredicate?: (tool: StructuredTool) => boolean;
|
|
13
|
+
}
|
|
14
|
+
export type ExecutionMode = 'direct' | 'bytes';
|
|
15
|
+
export type OperationalMode = 'autonomous' | 'returnBytes';
|
|
16
|
+
export interface HederaAgentConfiguration {
|
|
17
|
+
signer: ServerSigner;
|
|
18
|
+
execution?: {
|
|
19
|
+
mode?: ExecutionMode;
|
|
20
|
+
operationalMode?: OperationalMode;
|
|
21
|
+
userAccountId?: string;
|
|
22
|
+
scheduleUserTransactions?: boolean;
|
|
23
|
+
scheduleUserTransactionsInBytesMode?: boolean;
|
|
24
|
+
};
|
|
25
|
+
ai?: {
|
|
26
|
+
provider?: AIProvider;
|
|
27
|
+
llm?: unknown;
|
|
28
|
+
apiKey?: string;
|
|
29
|
+
modelName?: string;
|
|
30
|
+
temperature?: number;
|
|
31
|
+
};
|
|
32
|
+
filtering?: ToolFilterConfig;
|
|
33
|
+
messaging?: {
|
|
34
|
+
systemPreamble?: string;
|
|
35
|
+
systemPostamble?: string;
|
|
36
|
+
conciseMode?: boolean;
|
|
37
|
+
};
|
|
38
|
+
extensions?: {
|
|
39
|
+
plugins?: BasePlugin[];
|
|
40
|
+
mirrorConfig?: Record<string, unknown>;
|
|
41
|
+
modelCapability?: string;
|
|
42
|
+
};
|
|
43
|
+
mcp?: {
|
|
44
|
+
servers?: MCPServerConfig[];
|
|
45
|
+
autoConnect?: boolean;
|
|
46
|
+
};
|
|
47
|
+
debug?: {
|
|
48
|
+
verbose?: boolean;
|
|
49
|
+
silent?: boolean;
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
export interface ConversationContext {
|
|
53
|
+
messages: BaseMessage[];
|
|
54
|
+
metadata?: Record<string, unknown>;
|
|
55
|
+
}
|
|
56
|
+
export interface ChatResponse {
|
|
57
|
+
output: string;
|
|
58
|
+
message?: string;
|
|
59
|
+
transactionBytes?: string;
|
|
60
|
+
receipt?: TransactionReceipt | object;
|
|
61
|
+
scheduleId?: string;
|
|
62
|
+
transactionId?: string;
|
|
63
|
+
notes?: string[];
|
|
64
|
+
error?: string;
|
|
65
|
+
intermediateSteps?: unknown;
|
|
66
|
+
rawToolOutput?: unknown;
|
|
67
|
+
tokenUsage?: TokenUsage;
|
|
68
|
+
cost?: CostCalculation;
|
|
69
|
+
metadata?: Record<string, unknown>;
|
|
70
|
+
[key: string]: unknown;
|
|
71
|
+
}
|
|
72
|
+
export interface UsageStats extends TokenUsage {
|
|
73
|
+
cost: CostCalculation;
|
|
74
|
+
}
|
|
75
|
+
export declare abstract class BaseAgent {
|
|
76
|
+
protected config: HederaAgentConfiguration;
|
|
77
|
+
protected logger: Logger;
|
|
78
|
+
protected agentKit: HederaAgentKit | undefined;
|
|
79
|
+
protected tools: StructuredTool[];
|
|
80
|
+
protected initialized: boolean;
|
|
81
|
+
protected tokenTracker: TokenUsageCallbackHandler | undefined;
|
|
82
|
+
constructor(config: HederaAgentConfiguration);
|
|
83
|
+
abstract boot(): Promise<void>;
|
|
84
|
+
abstract chat(message: string, context?: ConversationContext): Promise<ChatResponse>;
|
|
85
|
+
abstract shutdown(): Promise<void>;
|
|
86
|
+
abstract switchMode(mode: OperationalMode): void;
|
|
87
|
+
abstract getUsageStats(): UsageStats;
|
|
88
|
+
abstract getUsageLog(): UsageStats[];
|
|
89
|
+
abstract clearUsageStats(): void;
|
|
90
|
+
getCore(): HederaAgentKit | undefined;
|
|
91
|
+
protected filterTools(tools: StructuredTool[]): StructuredTool[];
|
|
92
|
+
protected buildSystemPrompt(): string;
|
|
93
|
+
isReady(): boolean;
|
|
94
|
+
}
|
|
95
|
+
export type { AIProvider, VercelAIProvider, BAMLProvider };
|
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BasePlugin, AgentOperationalMode, MirrorNodeConfig } from 'hedera-agent-kit';
|
|
2
|
+
import { NetworkType } from '@hashgraphonline/standards-sdk';
|
|
3
|
+
import { createAgent } from './agent-factory';
|
|
4
|
+
import { ChatResponse } from './base-agent';
|
|
2
5
|
import { HCS10Plugin } from './plugins/hcs-10/HCS10Plugin';
|
|
3
6
|
import { HCS2Plugin } from './plugins/hcs-2/HCS2Plugin';
|
|
4
7
|
import { InscribePlugin } from './plugins/inscribe/InscribePlugin';
|
|
8
|
+
import { HbarTransferPlugin } from './plugins/hbar-transfer/HbarTransferPlugin';
|
|
5
9
|
import { IStateManager } from '@hashgraphonline/standards-agent-kit';
|
|
6
|
-
import {
|
|
10
|
+
import { MCPServerConfig } from './mcp/types';
|
|
7
11
|
|
|
8
12
|
export interface ConversationalAgentOptions {
|
|
9
13
|
accountId: string;
|
|
@@ -22,6 +26,11 @@ export interface ConversationalAgentOptions {
|
|
|
22
26
|
mirrorNodeConfig?: MirrorNodeConfig;
|
|
23
27
|
disableLogging?: boolean;
|
|
24
28
|
enabledPlugins?: string[];
|
|
29
|
+
toolFilter?: (tool: {
|
|
30
|
+
name: string;
|
|
31
|
+
namespace?: string;
|
|
32
|
+
}) => boolean;
|
|
33
|
+
mcpServers?: MCPServerConfig[];
|
|
25
34
|
}
|
|
26
35
|
/**
|
|
27
36
|
* The ConversationalAgent class is an optional wrapper around the HederaConversationalAgent class,
|
|
@@ -33,22 +42,58 @@ export interface ConversationalAgentOptions {
|
|
|
33
42
|
* @returns A new instance of the ConversationalAgent class.
|
|
34
43
|
*/
|
|
35
44
|
export declare class ConversationalAgent {
|
|
36
|
-
|
|
45
|
+
private agent?;
|
|
37
46
|
hcs10Plugin: HCS10Plugin;
|
|
38
47
|
hcs2Plugin: HCS2Plugin;
|
|
39
48
|
inscribePlugin: InscribePlugin;
|
|
49
|
+
hbarTransferPlugin: HbarTransferPlugin;
|
|
40
50
|
stateManager: IStateManager;
|
|
41
51
|
private options;
|
|
42
52
|
private logger;
|
|
43
53
|
constructor(options: ConversationalAgentOptions);
|
|
54
|
+
/**
|
|
55
|
+
* Initialize the conversational agent with Hedera network connection and AI configuration
|
|
56
|
+
* @throws {Error} If account ID or private key is missing
|
|
57
|
+
* @throws {Error} If initialization fails
|
|
58
|
+
*/
|
|
44
59
|
initialize(): Promise<void>;
|
|
60
|
+
/**
|
|
61
|
+
* Get the HCS-10 plugin instance
|
|
62
|
+
* @returns {HCS10Plugin} The HCS-10 plugin instance
|
|
63
|
+
*/
|
|
45
64
|
getPlugin(): HCS10Plugin;
|
|
65
|
+
/**
|
|
66
|
+
* Get the state manager instance
|
|
67
|
+
* @returns {IStateManager} The state manager instance
|
|
68
|
+
*/
|
|
46
69
|
getStateManager(): IStateManager;
|
|
47
|
-
|
|
70
|
+
/**
|
|
71
|
+
* Get the underlying agent instance
|
|
72
|
+
* @returns {ReturnType<typeof createAgent>} The agent instance
|
|
73
|
+
* @throws {Error} If agent is not initialized
|
|
74
|
+
*/
|
|
75
|
+
getAgent(): ReturnType<typeof createAgent>;
|
|
76
|
+
/**
|
|
77
|
+
* Get the conversational agent instance (alias for getAgent)
|
|
78
|
+
* @returns {ReturnType<typeof createAgent>} The agent instance
|
|
79
|
+
* @throws {Error} If agent is not initialized
|
|
80
|
+
*/
|
|
81
|
+
getConversationalAgent(): ReturnType<typeof createAgent>;
|
|
82
|
+
/**
|
|
83
|
+
* Process a message through the conversational agent
|
|
84
|
+
* @param {string} message - The message to process
|
|
85
|
+
* @param {Array<{type: 'human' | 'ai'; content: string}>} chatHistory - Previous chat history
|
|
86
|
+
* @returns {Promise<ChatResponse>} The agent's response
|
|
87
|
+
* @throws {Error} If agent is not initialized
|
|
88
|
+
*/
|
|
48
89
|
processMessage(message: string, chatHistory?: {
|
|
49
90
|
type: 'human' | 'ai';
|
|
50
91
|
content: string;
|
|
51
|
-
}[]): Promise<
|
|
92
|
+
}[]): Promise<ChatResponse>;
|
|
93
|
+
/**
|
|
94
|
+
* Create a ConversationalAgent with specific plugins enabled
|
|
95
|
+
*/
|
|
96
|
+
private static withPlugins;
|
|
52
97
|
/**
|
|
53
98
|
* Create a ConversationalAgent with only HTS (Hedera Token Service) tools enabled
|
|
54
99
|
*/
|
|
@@ -89,4 +134,16 @@ export declare class ConversationalAgent {
|
|
|
89
134
|
* Create a ConversationalAgent with minimal Hedera tools (no HCS standards)
|
|
90
135
|
*/
|
|
91
136
|
static minimal(options: ConversationalAgentOptions): ConversationalAgent;
|
|
137
|
+
/**
|
|
138
|
+
* Create a ConversationalAgent with MCP servers configured
|
|
139
|
+
*/
|
|
140
|
+
static withMCP(options: ConversationalAgentOptions, mcpServers: MCPServerConfig[]): ConversationalAgent;
|
|
141
|
+
/**
|
|
142
|
+
* Detect the private key type by querying the account info from mirror node
|
|
143
|
+
* @param {string} accountId - The Hedera account ID
|
|
144
|
+
* @param {string} privateKey - The private key string
|
|
145
|
+
* @param {NetworkType} network - The Hedera network
|
|
146
|
+
* @returns {Promise<PrivateKey>} The appropriate PrivateKey instance
|
|
147
|
+
*/
|
|
148
|
+
private detectPrivateKeyType;
|
|
92
149
|
}
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("hedera-agent-kit"),t=require("@hashgraphonline/standards-agent-kit"),i=require("@hashgraphonline/standards-sdk"),n=require("@hashgraph/sdk");class o extends e.BasePlugin{constructor(){super(...arguments),this.id="hcs-10",this.name="HCS-10 Plugin",this.description="HCS-10 agent tools for decentralized agent registration, connections, and messaging on Hedera",this.version="1.0.0",this.author="Hashgraph Online",this.namespace="hcs10",this.tools=[]}async initialize(e){await super.initialize(e);if(e.config.hederaKit)try{this.stateManager=e.stateManager||new t.OpenConvaiState,this.initializeTools(),this.context.logger.info("HCS-10 Plugin initialized successfully")}catch(i){this.context.logger.error("Failed to initialize HCS-10 plugin:",i)}else this.context.logger.warn("HederaKit not found in context. HCS-10 tools will not be available.")}initializeTools(){if(!this.stateManager)throw new Error("StateManager must be initialized before creating tools");const e=this.context.config.hederaKit;if(!e)throw new Error("HederaKit not found in context config");const i=new t.HCS10Builder(e,this.stateManager);this.tools=[new t.RegisterAgentTool({hederaKit:e,hcs10Builder:i,logger:this.context.logger}),new t.FindRegistrationsTool({hederaKit:e,hcs10Builder:i,logger:this.context.logger}),new t.RetrieveProfileTool({hederaKit:e,hcs10Builder:i,logger:this.context.logger}),new t.InitiateConnectionTool({hederaKit:e,hcs10Builder:i,logger:this.context.logger}),new t.ListConnectionsTool({hederaKit:e,hcs10Builder:i,logger:this.context.logger}),new t.SendMessageToConnectionTool({hederaKit:e,hcs10Builder:i,logger:this.context.logger}),new t.CheckMessagesTool({hederaKit:e,hcs10Builder:i,logger:this.context.logger}),new t.ConnectionMonitorTool({hederaKit:e,hcs10Builder:i,logger:this.context.logger}),new t.ManageConnectionRequestsTool({hederaKit:e,hcs10Builder:i,logger:this.context.logger}),new t.AcceptConnectionRequestTool({hederaKit:e,hcs10Builder:i,logger:this.context.logger}),new t.ListUnapprovedConnectionRequestsTool({hederaKit:e,hcs10Builder:i,logger:this.context.logger})]}getTools(){return this.tools}getStateManager(){return this.stateManager}async cleanup(){this.tools=[],delete this.stateManager,this.context?.logger&&this.context.logger.info("HCS-10 Plugin cleaned up")}}class s extends e.BasePlugin{constructor(){super(...arguments),this.id="hcs-2",this.name="HCS-2 Plugin",this.description="HCS-2 registry management tools for decentralized registries on Hedera",this.version="1.0.0",this.author="Hashgraph Online",this.namespace="hcs2",this.tools=[]}async initialize(e){await super.initialize(e);if(e.config.hederaKit)try{this.initializeTools(),this.context.logger.info("HCS-2 Plugin initialized successfully")}catch(t){this.context.logger.error("Failed to initialize HCS-2 plugin:",t)}else this.context.logger.warn("HederaKit not found in context. HCS-2 tools will not be available.")}initializeTools(){const e=this.context.config.hederaKit;if(!e)throw new Error("HederaKit not found in context config");const i=new t.HCS2Builder(e);this.tools=[new t.CreateRegistryTool({hederaKit:e,hcs2Builder:i,logger:this.context.logger}),new t.RegisterEntryTool({hederaKit:e,hcs2Builder:i,logger:this.context.logger}),new t.UpdateEntryTool({hederaKit:e,hcs2Builder:i,logger:this.context.logger}),new t.DeleteEntryTool({hederaKit:e,hcs2Builder:i,logger:this.context.logger}),new t.MigrateRegistryTool({hederaKit:e,hcs2Builder:i,logger:this.context.logger}),new t.QueryRegistryTool({hederaKit:e,hcs2Builder:i,logger:this.context.logger})]}getTools(){return this.tools}async cleanup(){this.tools=[],this.context?.logger&&this.context.logger.info("HCS-2 Plugin cleaned up")}}class r extends e.BasePlugin{constructor(){super(...arguments),this.id="inscribe",this.name="Inscribe Plugin",this.description="Content inscription tools for storing data on Hedera Consensus Service",this.version="1.0.0",this.author="Hashgraph Online",this.namespace="inscribe",this.tools=[]}async initialize(e){await super.initialize(e);if(e.config.hederaKit)try{this.initializeTools(),this.context.logger.info("Inscribe Plugin initialized successfully")}catch(t){this.context.logger.error("Failed to initialize Inscribe plugin:",t)}else this.context.logger.warn("HederaKit not found in context. Inscription tools will not be available.")}initializeTools(){const e=this.context.config.hederaKit;if(!e)throw new Error("HederaKit not found in context config");const i=new t.InscriberBuilder(e);this.tools=[new t.InscribeFromUrlTool({hederaKit:e,inscriberBuilder:i,logger:this.context.logger}),new t.InscribeFromFileTool({hederaKit:e,inscriberBuilder:i,logger:this.context.logger}),new t.InscribeFromBufferTool({hederaKit:e,inscriberBuilder:i,logger:this.context.logger}),new t.InscribeHashinalTool({hederaKit:e,inscriberBuilder:i,logger:this.context.logger}),new t.RetrieveInscriptionTool({hederaKit:e,inscriberBuilder:i,logger:this.context.logger})]}getTools(){return this.tools}async cleanup(){this.tools=[],this.context?.logger&&this.context.logger.info("Inscribe Plugin cleaned up")}}const a=e=>`You are a helpful assistant managing Hashgraph Online HCS-10 connections, messages, HCS-2 registries, and content inscription.\n\nYou have access to tools for:\n- HCS-10: registering agents, finding registered agents, initiating connections, listing active connections, sending messages over connections, and checking for new messages\n- HCS-2: creating registries, registering entries, updating entries, deleting entries, migrating registries, and querying registry contents\n- Inscription: inscribing content from URLs, files, or buffers, creating Hashinal NFTs, and retrieving inscriptions\n\n*** IMPORTANT CONTEXT ***\nYou are currently operating as agent: ${e} on the Hashgraph Online network\nWhen users ask about "my profile", "my account", "my connections", etc., use this account ID: ${e}\n\nRemember the connection numbers when listing connections, as users might refer to them.`;class l{constructor(e){this.options=e,this.stateManager=e.stateManager||new t.OpenConvaiState,this.hcs10Plugin=new o,this.hcs2Plugin=new s,this.inscribePlugin=new r,this.logger=new i.Logger({module:"ConversationalAgent"})}async initialize(){const{accountId:t,privateKey:o,network:s="testnet",openAIApiKey:r,openAIModelName:l="gpt-4o",verbose:g=!1,operationalMode:c="autonomous",userAccountId:h,customSystemMessagePreamble:u,customSystemMessagePostamble:d,additionalPlugins:w=[],scheduleUserTransactionsInBytesMode:p,mirrorNodeConfig:f,disableLogging:b}=this.options;if(!t||!o)throw new Error("Account ID and private key are required");try{const x=new i.HederaMirrorNode(s,this.logger),C=await x.requestAccount(t),m=C?.key?._type||"";let y;y=m?.toLowerCase()?.includes("ecdsa")?n.PrivateKey.fromStringECDSA(o):n.PrivateKey.fromStringED25519(o);const P=new e.ServerSigner(t,y,s),S=[this.hcs10Plugin,this.hcs2Plugin,this.inscribePlugin],v=e.getAllHederaCorePlugins();let H;if(this.options.enabledPlugins){const e=new Set(this.options.enabledPlugins);H=[...[...S,...v].filter(t=>e.has(t.id)),...w]}else H=[...S,...v,...w];const T={pluginConfig:{plugins:H,appConfig:{stateManager:this.stateManager}},openAIApiKey:r,openAIModelName:l,verbose:g,operationalMode:c,userAccountId:h,customSystemMessagePreamble:u||a(t),...void 0!==d&&{customSystemMessagePostamble:d},...void 0!==p&&{scheduleUserTransactionsInBytesMode:p},...void 0!==f&&{mirrorNodeConfig:f},...void 0!==b&&{disableLogging:b}};this.conversationalAgent=new e.HederaConversationalAgent(P,T),await this.conversationalAgent.initialize()}catch(x){throw this.logger.error("Failed to initialize ConversationalAgent:",x),x}}getPlugin(){return this.hcs10Plugin}getStateManager(){return this.stateManager}getConversationalAgent(){if(!this.conversationalAgent)throw new Error("ConversationalAgent not initialized. Call initialize() first.");return this.conversationalAgent}async processMessage(e,t=[]){if(!this.conversationalAgent)throw new Error("ConversationalAgent not initialized. Call initialize() first.");return this.conversationalAgent.processMessage(e,t)}static withHTS(e){return new l({...e,enabledPlugins:["hts-token"]})}static withHCS2(e){return new l({...e,enabledPlugins:["hcs-2"]})}static withHCS10(e){return new l({...e,enabledPlugins:["hcs-10"]})}static withInscribe(e){return new l({...e,enabledPlugins:["inscribe"]})}static withAccount(e){return new l({...e,enabledPlugins:["account"]})}static withFileService(e){return new l({...e,enabledPlugins:["file-service"]})}static withConsensusService(e){return new l({...e,enabledPlugins:["consensus-service"]})}static withSmartContract(e){return new l({...e,enabledPlugins:["smart-contract"]})}static withAllStandards(e){return new l({...e,enabledPlugins:["hcs-10","hcs-2","inscribe"]})}static minimal(e){return new l({...e,enabledPlugins:[]})}}exports.ConversationalAgent=l,exports.HCS10Plugin=o,exports.HCS2Plugin=s,exports.InscribePlugin=r,Object.keys(e).forEach(t=>{"default"===t||Object.prototype.hasOwnProperty.call(exports,t)||Object.defineProperty(exports,t,{enumerable:!0,get:()=>e[t]})});
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("hedera-agent-kit"),t=require("@hashgraphonline/standards-agent-kit"),n=require("zod"),r=require("@hashgraph/sdk"),o=require("bignumber.js"),i=require("@hashgraphonline/standards-sdk"),s=require("langchain/agents"),a=require("@langchain/core/prompts"),c=require("@langchain/openai"),l=require("@modelcontextprotocol/sdk/client/index.js"),g=require("@modelcontextprotocol/sdk/client/stdio.js"),h=require("@langchain/core/tools"),u=require("@langchain/core/messages");class d extends e.BasePlugin{constructor(){super(...arguments),this.id="hcs-10",this.name="HCS-10 Plugin",this.description="HCS-10 agent tools for decentralized agent registration, connections, and messaging on Hedera",this.version="1.0.0",this.author="Hashgraph Online",this.namespace="hcs10",this.tools=[]}async initialize(e){await super.initialize(e);if(e.config.hederaKit)try{this.stateManager=e.stateManager||new t.OpenConvaiState,this.initializeTools(),this.context.logger.info("HCS-10 Plugin initialized successfully")}catch(n){this.context.logger.error("Failed to initialize HCS-10 plugin:",n)}else this.context.logger.warn("HederaKit not found in context. HCS-10 tools will not be available.")}initializeTools(){if(!this.stateManager)throw new Error("StateManager must be initialized before creating tools");const e=this.context.config.hederaKit;if(!e)throw new Error("HederaKit not found in context config");const n=new t.HCS10Builder(e,this.stateManager);this.tools=[new t.RegisterAgentTool({hederaKit:e,hcs10Builder:n,logger:this.context.logger}),new t.FindRegistrationsTool({hederaKit:e,hcs10Builder:n,logger:this.context.logger}),new t.RetrieveProfileTool({hederaKit:e,hcs10Builder:n,logger:this.context.logger}),new t.InitiateConnectionTool({hederaKit:e,hcs10Builder:n,logger:this.context.logger}),new t.ListConnectionsTool({hederaKit:e,hcs10Builder:n,logger:this.context.logger}),new t.SendMessageToConnectionTool({hederaKit:e,hcs10Builder:n,logger:this.context.logger}),new t.CheckMessagesTool({hederaKit:e,hcs10Builder:n,logger:this.context.logger}),new t.ConnectionMonitorTool({hederaKit:e,hcs10Builder:n,logger:this.context.logger}),new t.ManageConnectionRequestsTool({hederaKit:e,hcs10Builder:n,logger:this.context.logger}),new t.AcceptConnectionRequestTool({hederaKit:e,hcs10Builder:n,logger:this.context.logger}),new t.ListUnapprovedConnectionRequestsTool({hederaKit:e,hcs10Builder:n,logger:this.context.logger})]}getTools(){return this.tools}getStateManager(){return this.stateManager}async cleanup(){this.tools=[],delete this.stateManager,this.context?.logger&&this.context.logger.info("HCS-10 Plugin cleaned up")}}class m extends e.BasePlugin{constructor(){super(...arguments),this.id="hcs-2",this.name="HCS-2 Plugin",this.description="HCS-2 registry management tools for decentralized registries on Hedera",this.version="1.0.0",this.author="Hashgraph Online",this.namespace="hcs2",this.tools=[]}async initialize(e){await super.initialize(e);if(e.config.hederaKit)try{this.initializeTools(),this.context.logger.info("HCS-2 Plugin initialized successfully")}catch(t){this.context.logger.error("Failed to initialize HCS-2 plugin:",t)}else this.context.logger.warn("HederaKit not found in context. HCS-2 tools will not be available.")}initializeTools(){const e=this.context.config.hederaKit;if(!e)throw new Error("HederaKit not found in context config");const n=new t.HCS2Builder(e);this.tools=[new t.CreateRegistryTool({hederaKit:e,hcs2Builder:n,logger:this.context.logger}),new t.RegisterEntryTool({hederaKit:e,hcs2Builder:n,logger:this.context.logger}),new t.UpdateEntryTool({hederaKit:e,hcs2Builder:n,logger:this.context.logger}),new t.DeleteEntryTool({hederaKit:e,hcs2Builder:n,logger:this.context.logger}),new t.MigrateRegistryTool({hederaKit:e,hcs2Builder:n,logger:this.context.logger}),new t.QueryRegistryTool({hederaKit:e,hcs2Builder:n,logger:this.context.logger})]}getTools(){return this.tools}async cleanup(){this.tools=[],this.context?.logger&&this.context.logger.info("HCS-2 Plugin cleaned up")}}class p extends e.BasePlugin{constructor(){super(...arguments),this.id="inscribe",this.name="Inscribe Plugin",this.description="Content inscription tools for storing data on Hedera Consensus Service",this.version="1.0.0",this.author="Hashgraph Online",this.namespace="inscribe",this.tools=[]}async initialize(e){await super.initialize(e);if(e.config.hederaKit)try{this.initializeTools(),this.context.logger.info("Inscribe Plugin initialized successfully")}catch(t){this.context.logger.error("Failed to initialize Inscribe plugin:",t)}else this.context.logger.warn("HederaKit not found in context. Inscription tools will not be available.")}initializeTools(){const e=this.context.config.hederaKit;if(!e)throw new Error("HederaKit not found in context config");const n=new t.InscriberBuilder(e);this.tools=[new t.InscribeFromUrlTool({hederaKit:e,inscriberBuilder:n,logger:this.context.logger}),new t.InscribeFromFileTool({hederaKit:e,inscriberBuilder:n,logger:this.context.logger}),new t.InscribeFromBufferTool({hederaKit:e,inscriberBuilder:n,logger:this.context.logger}),new t.InscribeHashinalTool({hederaKit:e,inscriberBuilder:n,logger:this.context.logger}),new t.RetrieveInscriptionTool({hederaKit:e,inscriberBuilder:n,logger:this.context.logger})]}getTools(){return this.tools}async cleanup(){this.tools=[],this.context?.logger&&this.context.logger.info("Inscribe Plugin cleaned up")}}class f extends e.BaseServiceBuilder{constructor(e){super(e)}transferHbar(e,t=!0){this.clearNotes();const n=new r.TransferTransaction;if(!e.transfers||0===e.transfers.length)throw new Error("HbarTransferParams must include at least one transfer.");let i=new o(0),s=!1;if(t&&this.kit.userAccountId&&"provideBytes"===this.kit.operationalMode&&1===e.transfers.length){const t=e.transfers[0],i="string"==typeof t.amount||"number"==typeof t.amount?t.amount:t.amount.toString(),a=new o(i);if(a.isPositive()){const e="string"==typeof t.accountId?r.AccountId.fromString(t.accountId):t.accountId,i=a.toFixed(8,o.ROUND_DOWN),c=r.Hbar.fromString(i);this.logger.info(`[AccountBuilder.transferHbar] Configuring user-initiated scheduled transfer: ${c.toString()} from ${this.kit.userAccountId} to ${e.toString()}`),this.addNote(`Configured HBAR transfer from your account (${this.kit.userAccountId}) to ${e.toString()} for ${c.toString()}.`),n.addHbarTransfer(e,c),n.addHbarTransfer(r.AccountId.fromString(this.kit.userAccountId),c.negated()),s=!0}}if(!s){const t=[];for(const n of e.transfers){const e="string"==typeof n.accountId?r.AccountId.fromString(n.accountId):n.accountId,s="string"==typeof n.amount||"number"==typeof n.amount?n.amount:n.amount.toString(),a=new o(s),c=a.toFixed(8,o.ROUND_DOWN);this.logger.info(`Processing transfer: ${s} HBAR (rounded to ${c}) for account ${e.toString()}`);const l=r.Hbar.fromString(c);t.push({accountId:e,amount:a,hbar:l});const g=l.toTinybars();i=i.plus(g.toString())}if(!i.isZero()&&(this.logger.warn(`Transfer sum not zero: ${i.toString()} tinybars off. Adjusting last transfer.`),t.length>0)){const e=t[t.length-1],n=i.dividedBy(-1e8),s=e.amount.plus(n).toFixed(8,o.ROUND_DOWN);e.hbar=r.Hbar.fromString(s),this.logger.info(`Adjusted last transfer for ${e.accountId.toString()} to ${s} HBAR`)}for(const e of t)n.addHbarTransfer(e.accountId,e.hbar)}return void 0!==e.memo&&(null===e.memo?this.logger.warn("Received null for memo in transferHbar."):n.setTransactionMemo(e.memo)),this.setCurrentTransaction(n),this}}const y=n.z.object({accountId:n.z.string().describe('Account ID for the transfer (e.g., "0.0.xxxx").'),amount:n.z.union([n.z.number(),n.z.string()]).describe("HBAR amount. Positive for credit, negative for debit. Builder handles Hbar unit & sum validation.")}),w=n.z.object({transfers:n.z.array(y).min(1).describe('Array of ALL transfers for this transaction. For multi-party transfers (e.g., "A sends 5 to C and B sends 3 to C"), include all transfers here: [{accountId: "A", amount: -5}, {accountId: "B", amount: -3}, {accountId: "C", amount: 8}]. Amounts must sum to zero.'),memo:n.z.string().optional().describe("Optional. Memo for the transaction.")});class b extends e.BaseHederaTransactionTool{constructor(){super(...arguments),this.name="hedera-account-transfer-hbar-v2",this.description='PRIMARY TOOL FOR HBAR TRANSFERS: Transfers HBAR between accounts. Supports multiple transfers in a single transaction - when multiple accounts need to send/receive HBAR (e.g., "A sends 5 HBAR to C and B sends 3 HBAR to C"), include ALL transfers in one transfers array. The sum of all transfers must equal zero. Use this for scheduled transactions and multi-signature scenarios.',this.specificInputSchema=w,this.namespace="account"}getServiceBuilder(){return new f(this.hederaKit)}async callBuilderMethod(e,t){await e.transferHbar(t)}}class x extends e.BasePlugin{constructor(){super(...arguments),this.id="hbar-transfer",this.name="HBAR Transfer Plugin",this.description="HBAR transfer tool with proper decimal handling for multi-signature transactions",this.version="1.0.0",this.author="Hashgraph Online",this.namespace="account",this.tools=[]}async initialize(e){await super.initialize(e);if(e.config.hederaKit)try{this.initializeTools(),this.context.logger.info("HBAR Transfer Plugin initialized successfully")}catch(t){this.context.logger.error("Failed to initialize HBAR Transfer plugin:",t)}else this.context.logger.warn("HederaKit not found in context. HBAR transfer tools will not be available.")}initializeTools(){const e=this.context.config.hederaKit;if(!e)throw new Error("HederaKit not found in context config");this.tools=[new b({hederaKit:e,logger:this.context.logger})]}getTools(){return this.tools}async shutdown(){this.tools=[]}}class v{constructor(e){this.config=e,this.tools=[],this.initialized=!1,this.logger=new i.Logger({module:"BaseAgent",silent:e.debug?.silent||!1})}getCore(){return this.agentKit}filterTools(e){let t=[...e];const n=this.config.filtering;return n?(n.namespaceWhitelist?.length&&(t=t.filter(e=>{const t=e.namespace;return!t||n.namespaceWhitelist.includes(t)})),n.toolBlacklist?.length&&(t=t.filter(e=>!n.toolBlacklist.includes(e.name))),n.toolPredicate&&(t=t.filter(n.toolPredicate)),this.logger.debug(`Filtered tools: ${e.length} → ${t.length}`),t):t}buildSystemPrompt(){const e=[],t=this.config.signer.getAccountId().toString(),n=this.config.execution?.userAccountId;this.config.messaging?.systemPreamble&&e.push(this.config.messaging.systemPreamble),e.push(`You are a helpful Hedera assistant. Your primary operator account is ${t}. You have tools to interact with the Hedera network. When using any tool, provide all necessary parameters as defined by that tool's schema and description.`),n&&e.push(`The user you are assisting has a personal Hedera account ID: ${n}. IMPORTANT: When the user says things like "I want to send HBAR" or "transfer my tokens", you MUST use ${n} as the sender/from account. For example, if user says "I want to send 2 HBAR to 0.0.800", you must set up a transfer where ${n} sends the HBAR, not your operator account.`);return"autonomous"===(this.config.execution?.operationalMode||"returnBytes")?e.push(`\nOPERATIONAL MODE: 'autonomous'. Your goal is to execute transactions directly using your tools. Your account ${t} will be the payer for these transactions. Even if the user's account (${n||"a specified account"}) is the actor in the transaction body (e.g., sender of HBAR), you (the agent with operator ${t}) are still executing and paying. For HBAR transfers, ensure the amounts in the 'transfers' array sum to zero (as per tool schema), balancing with your operator account if necessary.`):this.config.execution?.scheduleUserTransactionsInBytesMode&&n?e.push(`\nOPERATIONAL MODE: 'returnBytes' with scheduled transactions for user actions. When a user asks for a transaction to be prepared (e.g., creating a token, topic, transferring assets for them to sign, etc), you MUST default to creating a Scheduled Transaction using the appropriate tool with the metaOption 'schedule: true'. The user (with account ID ${n}) will be the one to ultimately pay for and (if needed) sign the inner transaction. Your operator account (${t}) will pay for creating the schedule entity itself. You MUST return the ScheduleId and details of the scheduled operation in a structured JSON format with these fields: success, op, schedule_id, description, payer_account_id_scheduled_tx, and scheduled_transaction_details.`):e.push(`\nOPERATIONAL MODE: 'returnBytes'. Your goal is to provide transaction bytes directly. When a user asks for a transaction to be prepared (e.g., for them to sign, or for scheduling without the default scheduling flow), you MUST call the appropriate tool. If you want raw bytes for the user to sign for their own account ${n||"if specified"}, ensure the tool constructs the transaction body accordingly and use metaOption 'returnBytes: true' if available, or ensure the builder is configured for the user.`),!1!==this.config.messaging?.conciseMode&&e.push("\nAlways be concise. If the tool provides a JSON string as its primary output (especially in returnBytes mode), make your accompanying text brief. If the tool does not provide JSON output or an error occurs, your narrative becomes primary; if notes were generated by the tool in such cases, append them to your textual response."),this.config.messaging?.systemPostamble&&e.push(this.config.messaging.systemPostamble),e.join("\n")}isReady(){return this.initialized}}class T{constructor(e){this.clients=new Map,this.tools=new Map,this.logger=e}async connectServer(e){try{if(this.isServerConnected(e.name))return{serverName:e.name,connected:!1,error:`Server ${e.name} is already connected`,tools:[]};if(e.transport&&"stdio"!==e.transport)throw new Error(`Transport ${e.transport} not yet supported`);const t=new g.StdioClientTransport({command:e.command,args:e.args,...e.env&&{env:e.env}}),n=new l.Client({name:`conversational-agent-${e.name}`,version:"1.0.0"},{capabilities:{}});await n.connect(t),this.clients.set(e.name,n);const r=(await n.listTools()).tools.map(t=>({...t,serverName:e.name}));return this.tools.set(e.name,r),this.logger.info(`Connected to MCP server ${e.name} with ${r.length} tools`),{serverName:e.name,connected:!0,tools:r}}catch(t){return this.logger.error(`Failed to connect to MCP server ${e.name}:`,t),{serverName:e.name,connected:!1,error:t instanceof Error?t.message:"Unknown error",tools:[]}}}async executeTool(e,t,n){const r=this.clients.get(e);if(!r)throw new Error(`MCP server ${e} not connected`);this.logger.debug(`Executing MCP tool ${t} on server ${e}`,n);try{return await r.callTool({name:t,arguments:n})}catch(o){throw this.logger.error(`Error executing MCP tool ${t}:`,o),o}}async disconnectAll(){for(const[t,n]of this.clients)try{await n.close(),this.logger.info(`Disconnected from MCP server ${t}`)}catch(e){this.logger.error(`Error disconnecting MCP server ${t}:`,e)}this.clients.clear(),this.tools.clear()}getAllTools(){const e=[];for(const t of this.tools.values())e.push(...t);return e}getServerTools(e){return this.tools.get(e)||[]}isServerConnected(e){return this.clients.has(e)}getConnectedServers(){return Array.from(this.clients.keys())}}function C(e,t,n){const r=S(e.inputSchema),o=`${e.serverName}_${e.name}`.replace(/[^a-zA-Z0-9_]/g,"_");let i=e.description||`MCP tool ${e.name} from ${e.serverName}`;return n?.toolDescriptions?.[e.name]&&(i=`${i}\n\n${n.toolDescriptions[e.name]}`),n?.additionalContext&&(i=`${i}\n\nContext: ${n.additionalContext}`),new h.DynamicStructuredTool({name:o,description:i,schema:r,func:async n=>{try{const r=await t.executeTool(e.serverName,e.name,n);if("string"==typeof r)return r;if(r&&"object"==typeof r&&"content"in r){const e=r.content;if(Array.isArray(e)){return e.filter(e=>"object"==typeof e&&null!==e&&"type"in e&&"text"===e.type&&"text"in e).map(e=>e.text).join("\n")}return JSON.stringify(e)}return JSON.stringify(r)}catch(r){const t=r instanceof Error?r.message:"Unknown error";return`Error executing MCP tool ${e.name}: ${t}`}}})}function S(e){if(!e||"object"!=typeof e)return n.z.object({});const t=e;if(t.type&&"object"!==t.type)return A(t);if(!t.properties||"object"!=typeof t.properties)return n.z.object({});const r={};for(const[n,o]of Object.entries(t.properties)){let e=A(o);Array.isArray(t.required)&&t.required.includes(n)||(e=e.optional()),r[n]=e}return n.z.object(r)}function A(e){if(!e||"object"!=typeof e||!("type"in e))return n.z.unknown();const t=e;let r;switch(t.type){case"string":r=n.z.string(),t.enum&&Array.isArray(t.enum)&&(r=n.z.enum(t.enum));break;case"number":r=n.z.number(),"minimum"in t&&"number"==typeof t.minimum&&(r=r.min(t.minimum)),"maximum"in t&&"number"==typeof t.maximum&&(r=r.max(t.maximum));break;case"integer":r=n.z.number().int(),"minimum"in t&&"number"==typeof t.minimum&&(r=r.min(t.minimum)),"maximum"in t&&"number"==typeof t.maximum&&(r=r.max(t.maximum));break;case"boolean":r=n.z.boolean();break;case"array":r=t.items?n.z.array(A(t.items)):n.z.array(n.z.unknown());break;case"object":r="properties"in t?S(t):n.z.object({}).passthrough();break;default:r=n.z.unknown()}return"description"in t&&"string"==typeof t.description&&(r=r.describe(t.description)),r}class P extends v{constructor(){super(...arguments),this.systemMessage=""}async boot(){if(this.initialized)this.logger.warn("Agent already initialized");else try{this.agentKit=await this.createAgentKit(),await this.agentKit.initialize();const t=this.config.ai?.modelName||process.env.OPENAI_MODEL_NAME||"gpt-4o-mini";this.tokenTracker=new e.TokenUsageCallbackHandler(t);const n=this.agentKit.getAggregatedLangChainTools();this.tools=this.filterTools(n),this.config.mcp?.servers&&this.config.mcp.servers.length>0&&await this.initializeMCP(),this.systemMessage=this.buildSystemPrompt(),await this.createExecutor(),this.initialized=!0,this.logger.info("LangChain Hedera agent initialized")}catch(t){throw this.logger.error("Failed to initialize agent:",t),t}}async chat(t,n){if(!this.initialized||!this.executor)throw new Error("Agent not initialized. Call boot() first.");try{const o=await this.executor.invoke({input:t,chat_history:n?.messages||[]});let i={output:o.output||"",message:o.output||"",notes:[]};const s=o?.intermediateSteps?.[0]?.observation;if(s&&"string"==typeof s&&this.isJSON(s))try{const e=JSON.parse(s);i={...i,...e}}catch(r){this.logger.error("Error parsing intermediate steps:",r)}if(i.output&&""!==i.output.trim()||(i.output="Agent action complete."),this.tokenTracker){const t=this.tokenTracker.getLatestTokenUsage();t&&(i.tokenUsage=t,i.cost=e.calculateTokenCostSync(t))}return i}catch(r){return this.handleError(r)}}async shutdown(){this.mcpManager&&await this.mcpManager.disconnectAll(),this.executor=void 0,this.agentKit=void 0,this.tools=[],this.initialized=!1,this.logger.info("Agent cleaned up")}switchMode(e){this.config.execution?this.config.execution.operationalMode=e:this.config.execution={operationalMode:e},this.agentKit&&(this.agentKit.operationalMode=e),this.systemMessage=this.buildSystemPrompt(),this.logger.info(`Operational mode switched to: ${e}`)}getUsageStats(){if(!this.tokenTracker)return{promptTokens:0,completionTokens:0,totalTokens:0,cost:{totalCost:0}};const t=this.tokenTracker.getTotalTokenUsage(),n=e.calculateTokenCostSync(t);return{...t,cost:n}}getUsageLog(){return this.tokenTracker?this.tokenTracker.getTokenUsageHistory().map(t=>({...t,cost:e.calculateTokenCostSync(t)})):[]}clearUsageStats(){this.tokenTracker&&(this.tokenTracker.reset(),this.logger.info("Usage statistics cleared"))}async createAgentKit(){const t=[...e.getAllHederaCorePlugins(),...this.config.extensions?.plugins||[]],n=this.config.execution?.operationalMode||"returnBytes",r=this.config.ai?.modelName||"gpt-4o";return new e.HederaAgentKit(this.config.signer,{plugins:t},n,this.config.execution?.userAccountId,this.config.execution?.scheduleUserTransactionsInBytesMode??!0,void 0,r,this.config.extensions?.mirrorConfig,this.config.debug?.silent??!1)}async createExecutor(){let e;if(this.config.ai?.provider&&this.config.ai.provider.getModel)e=this.config.ai.provider.getModel();else if(this.config.ai?.llm)e=this.config.ai.llm;else{const t=this.config.ai?.apiKey||process.env.OPENAI_API_KEY;if(!t)throw new Error("OpenAI API key required");e=new c.ChatOpenAI({apiKey:t,modelName:this.config.ai?.modelName||"gpt-4o-mini",temperature:this.config.ai?.temperature??.1,callbacks:this.tokenTracker?[this.tokenTracker]:[]})}const t=a.ChatPromptTemplate.fromMessages([["system",this.systemMessage],new a.MessagesPlaceholder("chat_history"),["human","{input}"],new a.MessagesPlaceholder("agent_scratchpad")]),n=this.tools,r=await s.createOpenAIToolsAgent({llm:e,tools:n,prompt:t});this.executor=new s.AgentExecutor({agent:r,tools:n,verbose:this.config.debug?.verbose??!1,returnIntermediateSteps:!0})}handleError(t){const n=t instanceof Error?t.message:"Unknown error";let r,o;this.logger.error("Chat error:",t),this.tokenTracker&&(r=this.tokenTracker.getLatestTokenUsage(),r&&(o=e.calculateTokenCostSync(r)));const i={output:"Sorry, I encountered an error processing your request.",message:"Error processing request.",error:n,notes:[]};return r&&(i.tokenUsage=r),o&&(i.cost=o),i}async initializeMCP(){this.mcpManager=new T(this.logger);for(const e of this.config.mcp.servers){if(!1===e.autoConnect){this.logger.info(`Skipping MCP server ${e.name} (autoConnect=false)`);continue}const t=await this.mcpManager.connectServer(e);if(t.connected){this.logger.info(`Connected to MCP server ${t.serverName} with ${t.tools.length} tools`);for(const n of t.tools){const t=C(n,this.mcpManager,e);this.tools.push(t)}}else this.logger.error(`Failed to connect to MCP server ${t.serverName}: ${t.error}`)}}isJSON(e){if("string"!=typeof e)return!1;const t=e.trim();if(!t)return!1;if(!(t.startsWith("{")&&t.endsWith("}")||t.startsWith("[")&&t.endsWith("]")))return!1;try{return JSON.parse(t),!0}catch{return!1}}}function k(e){const t=e.framework||"langchain";switch(t){case"langchain":return new P(e);case"vercel":throw new Error("Vercel AI SDK support coming soon");case"baml":throw new Error("BAML support coming soon");default:throw new Error(`Unknown framework: ${t}`)}}class M{constructor(e){this.model=e}async generate(e,t){const n=await this.model.invoke(e,t);return"string"==typeof n?n:n.toString()}async*stream(e,t){const n=await this.model.stream(e,t);for await(const r of n)yield"string"==typeof r?r:r.toString()}getModel(){return this.model}}const H=e=>`You are a helpful assistant managing Hashgraph Online HCS-10 connections, messages, HCS-2 registries, and content inscription.\n\nYou have access to tools for:\n- HCS-10: registering agents, finding registered agents, initiating connections, listing active connections, sending messages over connections, and checking for new messages\n- HCS-2: creating registries, registering entries, updating entries, deleting entries, migrating registries, and querying registry contents\n- Inscription: inscribing content from URLs, files, or buffers, creating Hashinal NFTs, and retrieving inscriptions\n\n*** IMPORTANT CONTEXT ***\nYou are currently operating as agent: ${e} on the Hashgraph Online network\nWhen users ask about "my profile", "my account", "my connections", etc., use this account ID: ${e}\n\nRemember the connection numbers when listing connections, as users might refer to them.`,I="gpt-4o",B="testnet",z="autonomous";class K{constructor(e){this.options=e,this.stateManager=e.stateManager||new t.OpenConvaiState,this.hcs10Plugin=new d,this.hcs2Plugin=new m,this.inscribePlugin=new p,this.hbarTransferPlugin=new x,this.logger=new i.Logger({module:"ConversationalAgent",silent:e.disableLogging||!1})}async initialize(){const{accountId:t,privateKey:n,network:r=B,openAIApiKey:o,openAIModelName:i=I,verbose:s=!1,operationalMode:a=z,userAccountId:l,customSystemMessagePreamble:g,customSystemMessagePostamble:h,additionalPlugins:u=[],mirrorNodeConfig:d,disableLogging:m,scheduleUserTransactionsInBytesMode:p}=this.options;if(!t||!n)throw new Error("Account ID and private key are required");try{const f=await this.detectPrivateKeyType(t,n,r),y=new e.ServerSigner(t,f,r),w=[this.hcs10Plugin,this.hcs2Plugin,this.inscribePlugin,this.hbarTransferPlugin],b=e.getAllHederaCorePlugins();let x;if(this.options.enabledPlugins){const e=new Set(this.options.enabledPlugins);x=[...[...w,...b].filter(t=>e.has(t.id)),...u]}else x=[...w,...b,...u];const v=new c.ChatOpenAI({apiKey:o,modelName:i,temperature:.1});this.agent=k({framework:"langchain",signer:y,execution:{mode:"autonomous"===a?"direct":"bytes",operationalMode:a,...l&&{userAccountId:l},...void 0!==p&&{scheduleUserTransactions:p}},ai:{provider:new M(v),temperature:.1},filtering:{toolPredicate:e=>"hedera-account-transfer-hbar"!==e.name&&!(this.options.toolFilter&&!this.options.toolFilter(e))},messaging:{systemPreamble:g||H(t),...h&&{systemPostamble:h},conciseMode:!0},extensions:{plugins:x,...d&&{mirrorConfig:d}},...this.options.mcpServers&&{mcp:{servers:this.options.mcpServers,autoConnect:!0}},debug:{verbose:s,silent:m??!1}});const T=x.find(e=>"hcs-10"===e.id);T&&(T.appConfig={stateManager:this.stateManager}),await this.agent.boot()}catch(f){throw this.logger.error("Failed to initialize ConversationalAgent:",f),f}}getPlugin(){return this.hcs10Plugin}getStateManager(){return this.stateManager}getAgent(){if(!this.agent)throw new Error("Agent not initialized. Call initialize() first.");return this.agent}getConversationalAgent(){return this.getAgent()}async processMessage(e,t=[]){if(!this.agent)throw new Error("Agent not initialized. Call initialize() first.");const n={messages:t.map(e=>"human"===e.type?new u.HumanMessage(e.content):new u.AIMessage(e.content))};return this.agent.chat(e,n)}static withPlugins(e,t){return new K({...e,enabledPlugins:t})}static withHTS(e){return this.withPlugins(e,["hts-token"])}static withHCS2(e){return this.withPlugins(e,["hcs-2"])}static withHCS10(e){return this.withPlugins(e,["hcs-10"])}static withInscribe(e){return this.withPlugins(e,["inscribe"])}static withAccount(e){return this.withPlugins(e,["account"])}static withFileService(e){return this.withPlugins(e,["file-service"])}static withConsensusService(e){return this.withPlugins(e,["consensus-service"])}static withSmartContract(e){return this.withPlugins(e,["smart-contract"])}static withAllStandards(e){return this.withPlugins(e,["hcs-10","hcs-2","inscribe"])}static minimal(e){return this.withPlugins(e,[])}static withMCP(e,t){return new K({...e,mcpServers:t})}async detectPrivateKeyType(e,t,n){const o=new i.HederaMirrorNode(n),s=await o.requestAccount(e),a=s?.key?._type||"";return a?.toLowerCase()?.includes("ecdsa")?r.PrivateKey.fromStringECDSA(t):r.PrivateKey.fromStringED25519(t)}}exports.BaseAgent=v,exports.ConversationalAgent=K,exports.HCS10Plugin=d,exports.HCS2Plugin=m,exports.HbarTransferPlugin=x,exports.InscribePlugin=p,exports.LangChainAgent=P,exports.LangChainProvider=M,exports.MCPServers={filesystem:e=>({name:"filesystem",command:"npx",args:["-y","@modelcontextprotocol/server-filesystem",e],transport:"stdio",autoConnect:!0,additionalContext:"This server provides access to files and directories in the current working directory.",toolDescriptions:{list_directory:'Use this tool when users ask about files in the "current directory" or "working directory".',read_file:"Use this tool when users ask to see or check files in the current directory."}}),github:e=>({name:"github",command:"npx",args:["-y","@modelcontextprotocol/server-github"],...e&&{env:{GITHUB_TOKEN:e}},transport:"stdio",autoConnect:!0}),slack:e=>({name:"slack",command:"npx",args:["-y","@modelcontextprotocol/server-slack"],env:{SLACK_TOKEN:e},transport:"stdio",autoConnect:!0}),googleDrive:e=>({name:"google-drive",command:"npx",args:["-y","@modelcontextprotocol/server-google-drive"],env:{GOOGLE_CREDENTIALS:e},transport:"stdio",autoConnect:!0}),postgres:e=>({name:"postgres",command:"npx",args:["-y","@modelcontextprotocol/server-postgres",e],transport:"stdio",autoConnect:!0}),sqlite:e=>({name:"sqlite",command:"npx",args:["-y","@modelcontextprotocol/server-sqlite",e],transport:"stdio",autoConnect:!0}),custom:e=>e},exports.OpenConvAIPlugin=d,exports.createAgent=k,exports.createMCPConfig=function(e,t=!0){return{mcpServers:e.map(e=>({...e,autoConnect:e.autoConnect??t}))}},exports.validateServerConfig=function(e){const t=[];return e.name||t.push("Server name is required"),e.command||t.push("Server command is required"),e.args&&Array.isArray(e.args)||t.push("Server args must be an array"),e.transport&&!["stdio","http","websocket"].includes(e.transport)&&t.push("Invalid transport type. Must be stdio, http, or websocket"),t},Object.keys(e).forEach(t=>{"default"===t||Object.prototype.hasOwnProperty.call(exports,t)||Object.defineProperty(exports,t,{enumerable:!0,get:()=>e[t]})});
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|