@hashgraphonline/conversational-agent 0.2.104 → 0.2.105

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (179) hide show
  1. package/README.md +64 -27
  2. package/cli/dist/CLIApp.d.ts +3 -1
  3. package/cli/dist/CLIApp.d.ts.map +1 -0
  4. package/cli/dist/CLIApp.js +6 -5
  5. package/cli/dist/CLIApp.js.map +1 -0
  6. package/cli/dist/app.d.ts +3 -1
  7. package/cli/dist/app.d.ts.map +1 -0
  8. package/cli/dist/app.js +2 -1
  9. package/cli/dist/app.js.map +1 -0
  10. package/cli/dist/cli.d.ts +1 -0
  11. package/cli/dist/cli.d.ts.map +1 -0
  12. package/cli/dist/cli.js +39 -3
  13. package/cli/dist/cli.js.map +1 -0
  14. package/cli/dist/components/ChatScreen.d.ts +9 -3
  15. package/cli/dist/components/ChatScreen.d.ts.map +1 -0
  16. package/cli/dist/components/ChatScreen.js +4 -3
  17. package/cli/dist/components/ChatScreen.js.map +1 -0
  18. package/cli/dist/components/LoadingScreen.d.ts +1 -0
  19. package/cli/dist/components/LoadingScreen.d.ts.map +1 -0
  20. package/cli/dist/components/LoadingScreen.js +2 -1
  21. package/cli/dist/components/LoadingScreen.js.map +1 -0
  22. package/cli/dist/components/MCPConfigScreen.d.ts +2 -2
  23. package/cli/dist/components/MCPConfigScreen.d.ts.map +1 -0
  24. package/cli/dist/components/MCPConfigScreen.js +77 -59
  25. package/cli/dist/components/MCPConfigScreen.js.map +1 -0
  26. package/cli/dist/components/ScreenRouter.d.ts +1 -0
  27. package/cli/dist/components/ScreenRouter.d.ts.map +1 -0
  28. package/cli/dist/components/ScreenRouter.js +6 -5
  29. package/cli/dist/components/ScreenRouter.js.map +1 -0
  30. package/cli/dist/components/SetupScreen.d.ts +1 -0
  31. package/cli/dist/components/SetupScreen.d.ts.map +1 -0
  32. package/cli/dist/components/SetupScreen.js +28 -26
  33. package/cli/dist/components/SetupScreen.js.map +1 -0
  34. package/cli/dist/components/StatusBadge.d.ts +4 -1
  35. package/cli/dist/components/StatusBadge.d.ts.map +1 -0
  36. package/cli/dist/components/StatusBadge.js +18 -22
  37. package/cli/dist/components/StatusBadge.js.map +1 -0
  38. package/cli/dist/components/TerminalWindow.d.ts +1 -0
  39. package/cli/dist/components/TerminalWindow.d.ts.map +1 -0
  40. package/cli/dist/components/TerminalWindow.js +2 -7
  41. package/cli/dist/components/TerminalWindow.js.map +1 -0
  42. package/cli/dist/components/WelcomeScreen.d.ts +1 -0
  43. package/cli/dist/components/WelcomeScreen.d.ts.map +1 -0
  44. package/cli/dist/components/WelcomeScreen.js +15 -15
  45. package/cli/dist/components/WelcomeScreen.js.map +1 -0
  46. package/cli/dist/headless-runner.d.ts +17 -0
  47. package/cli/dist/headless-runner.d.ts.map +1 -0
  48. package/cli/dist/headless-runner.js +128 -0
  49. package/cli/dist/headless-runner.js.map +1 -0
  50. package/cli/dist/hooks/useInitializeAgent.d.ts +4 -4
  51. package/cli/dist/hooks/useInitializeAgent.d.ts.map +1 -0
  52. package/cli/dist/hooks/useInitializeAgent.js +1 -0
  53. package/cli/dist/hooks/useInitializeAgent.js.map +1 -0
  54. package/cli/dist/hooks/useStableState.d.ts +2 -2
  55. package/cli/dist/hooks/useStableState.d.ts.map +1 -0
  56. package/cli/dist/hooks/useStableState.js +1 -0
  57. package/cli/dist/hooks/useStableState.js.map +1 -0
  58. package/cli/dist/managers/AgentManager.d.ts +3 -2
  59. package/cli/dist/managers/AgentManager.d.ts.map +1 -0
  60. package/cli/dist/managers/AgentManager.js +8 -6
  61. package/cli/dist/managers/AgentManager.js.map +1 -0
  62. package/cli/dist/managers/ConfigManager.d.ts +3 -2
  63. package/cli/dist/managers/ConfigManager.d.ts.map +1 -0
  64. package/cli/dist/managers/ConfigManager.js +23 -8
  65. package/cli/dist/managers/ConfigManager.js.map +1 -0
  66. package/cli/dist/types.d.ts +22 -1
  67. package/cli/dist/types.d.ts.map +1 -0
  68. package/cli/dist/types.js +15 -0
  69. package/cli/dist/types.js.map +1 -0
  70. package/dist/cjs/config/system-message.d.ts +1 -1
  71. package/dist/cjs/conversational-agent.d.ts +30 -2
  72. package/dist/cjs/core/tool-registry.d.ts +29 -0
  73. package/dist/cjs/forms/field-guidance-registry.d.ts +33 -0
  74. package/dist/cjs/index.cjs +1 -1
  75. package/dist/cjs/index.cjs.map +1 -1
  76. package/dist/cjs/index.d.ts +1 -0
  77. package/dist/cjs/mcp/types.d.ts +14 -3
  78. package/dist/cjs/plugins/index.d.ts +1 -0
  79. package/dist/cjs/plugins/inscribe/InscribePlugin.d.ts +1 -0
  80. package/dist/cjs/plugins/web-browser/WebBrowserPlugin.d.ts +14 -0
  81. package/dist/cjs/runtime/wallet-bridge.d.ts +26 -0
  82. package/dist/cjs/services/attachment-processor.d.ts +1 -2
  83. package/dist/cjs/services/content-store-manager.d.ts +1 -1
  84. package/dist/cjs/services/formatters/types.d.ts +3 -1
  85. package/dist/cjs/services/index.d.ts +1 -1
  86. package/dist/cjs/signers/browser-signer.d.ts +32 -0
  87. package/dist/esm/index.js +3 -0
  88. package/dist/esm/index.js.map +1 -1
  89. package/dist/esm/index10.js +13 -5
  90. package/dist/esm/index10.js.map +1 -1
  91. package/dist/esm/index13.js +157 -179
  92. package/dist/esm/index13.js.map +1 -1
  93. package/dist/esm/index15.js +9 -4
  94. package/dist/esm/index15.js.map +1 -1
  95. package/dist/esm/index18.js.map +1 -1
  96. package/dist/esm/index2.js +25 -27
  97. package/dist/esm/index2.js.map +1 -1
  98. package/dist/esm/index21.js +1 -1
  99. package/dist/esm/index21.js.map +1 -1
  100. package/dist/esm/index23.js +3 -3
  101. package/dist/esm/index24.js.map +1 -1
  102. package/dist/esm/index26.js.map +1 -1
  103. package/dist/esm/index3.js.map +1 -1
  104. package/dist/esm/index30.js.map +1 -1
  105. package/dist/esm/index31.js +6 -3
  106. package/dist/esm/index31.js.map +1 -1
  107. package/dist/esm/index33.js +5 -5
  108. package/dist/esm/index33.js.map +1 -1
  109. package/dist/esm/index36.js +8 -45
  110. package/dist/esm/index36.js.map +1 -1
  111. package/dist/esm/index37.js +41 -102
  112. package/dist/esm/index37.js.map +1 -1
  113. package/dist/esm/index38.js +107 -21
  114. package/dist/esm/index38.js.map +1 -1
  115. package/dist/esm/index39.js +63 -24
  116. package/dist/esm/index39.js.map +1 -1
  117. package/dist/esm/index4.js +43 -0
  118. package/dist/esm/index4.js.map +1 -1
  119. package/dist/esm/index40.js +78 -11
  120. package/dist/esm/index40.js.map +1 -1
  121. package/dist/esm/index41.js +21 -5
  122. package/dist/esm/index41.js.map +1 -1
  123. package/dist/esm/index42.js +5 -255
  124. package/dist/esm/index42.js.map +1 -1
  125. package/dist/esm/index43.js +12 -184
  126. package/dist/esm/index43.js.map +1 -1
  127. package/dist/esm/index44.js +322 -7
  128. package/dist/esm/index44.js.map +1 -1
  129. package/dist/esm/index45.js +174 -82
  130. package/dist/esm/index45.js.map +1 -1
  131. package/dist/esm/index46.js +30 -0
  132. package/dist/esm/index46.js.map +1 -0
  133. package/dist/esm/index47.js +10 -0
  134. package/dist/esm/index47.js.map +1 -0
  135. package/dist/esm/index48.js +98 -0
  136. package/dist/esm/index48.js.map +1 -0
  137. package/dist/esm/index5.js +2 -2
  138. package/dist/esm/index6.js +189 -29
  139. package/dist/esm/index6.js.map +1 -1
  140. package/dist/types/config/system-message.d.ts +1 -1
  141. package/dist/types/conversational-agent.d.ts +30 -2
  142. package/dist/types/core/tool-registry.d.ts +29 -0
  143. package/dist/types/forms/field-guidance-registry.d.ts +33 -0
  144. package/dist/types/index.d.ts +1 -0
  145. package/dist/types/mcp/types.d.ts +14 -3
  146. package/dist/types/plugins/index.d.ts +1 -0
  147. package/dist/types/plugins/inscribe/InscribePlugin.d.ts +1 -0
  148. package/dist/types/plugins/web-browser/WebBrowserPlugin.d.ts +14 -0
  149. package/dist/types/runtime/wallet-bridge.d.ts +26 -0
  150. package/dist/types/services/attachment-processor.d.ts +1 -2
  151. package/dist/types/services/content-store-manager.d.ts +1 -1
  152. package/dist/types/services/formatters/types.d.ts +3 -1
  153. package/dist/types/services/index.d.ts +1 -1
  154. package/dist/types/signers/browser-signer.d.ts +32 -0
  155. package/package.json +16 -11
  156. package/src/config/system-message.ts +3 -3
  157. package/src/conversational-agent.ts +318 -45
  158. package/src/core/tool-registry.ts +85 -0
  159. package/src/forms/field-guidance-registry.ts +213 -188
  160. package/src/forms/form-generator.ts +28 -12
  161. package/src/index.ts +1 -0
  162. package/src/langchain/form-aware-agent-executor.ts +6 -6
  163. package/src/langchain/langchain-agent.ts +1 -1
  164. package/src/mcp/mcp-client-manager.ts +12 -5
  165. package/src/mcp/types.ts +15 -3
  166. package/src/memory/content-storage.ts +19 -6
  167. package/src/memory/smart-memory-manager.ts +0 -1
  168. package/src/plugins/hbar/AccountBuilder.ts +16 -16
  169. package/src/plugins/hcs-10/HCS10Plugin.ts +38 -38
  170. package/src/plugins/hcs-2/HCS2Plugin.ts +2 -2
  171. package/src/plugins/index.ts +2 -1
  172. package/src/plugins/inscribe/InscribePlugin.ts +46 -2
  173. package/src/plugins/web-browser/WebBrowserPlugin.ts +128 -0
  174. package/src/runtime/wallet-bridge.ts +46 -0
  175. package/src/services/attachment-processor.ts +1 -1
  176. package/src/services/content-store-manager.ts +1 -1
  177. package/src/services/formatters/types.ts +3 -1
  178. package/src/services/index.ts +1 -1
  179. package/src/signers/browser-signer.ts +111 -0
@@ -2,13 +2,14 @@ import {
2
2
  ServerSigner,
3
3
  getAllHederaCorePlugins,
4
4
  BasePlugin,
5
+ AbstractSigner,
5
6
  } from 'hedera-agent-kit';
6
7
  import { Logger, type NetworkType } from '@hashgraphonline/standards-sdk';
7
8
  import { createAgent } from './agent-factory';
9
+ import BrowserSigner from './signers/browser-signer';
8
10
  import { LangChainProvider } from './providers';
9
11
  import type { ChatResponse, ConversationContext } from './base-agent';
10
12
  import { ChatOpenAI } from '@langchain/openai';
11
- import OpenAI from 'openai';
12
13
  import { ChatAnthropic } from '@langchain/anthropic';
13
14
  import {
14
15
  HumanMessage,
@@ -19,7 +20,13 @@ import type { AgentOperationalMode, MirrorNodeConfig } from 'hedera-agent-kit';
19
20
  import { HCS10Plugin } from './plugins/hcs-10/HCS10Plugin';
20
21
  import { HCS2Plugin } from './plugins/hcs-2/HCS2Plugin';
21
22
  import { InscribePlugin } from './plugins/inscribe/InscribePlugin';
23
+ import { getWalletBridgeProvider } from './runtime/wallet-bridge';
24
+ import {
25
+ InscriberBuilder,
26
+ SignerProviderRegistry,
27
+ } from '@hashgraphonline/standards-agent-kit';
22
28
  import { HbarPlugin } from './plugins/hbar/HbarPlugin';
29
+ import { WebBrowserPlugin } from './plugins/web-browser/WebBrowserPlugin';
23
30
  import { OpenConvaiState } from '@hashgraphonline/standards-agent-kit';
24
31
  import type { IStateManager } from '@hashgraphonline/standards-agent-kit';
25
32
  import { getSystemMessage } from './config/system-message';
@@ -52,6 +59,9 @@ export type AgentInstance = ReturnType<typeof createAgent>;
52
59
  export type MirrorNetwork = 'testnet' | 'mainnet' | 'previewnet';
53
60
 
54
61
  const DEFAULT_MODEL_NAME = 'gpt-4o';
62
+ const DEFAULT_OPENAI_MODEL = 'gpt-4o-mini';
63
+ const DEFAULT_OPENROUTER_MODEL = 'openai/gpt-4o-mini';
64
+ const DEFAULT_CLAUDE_MODEL = 'claude-3-7-sonnet-latest';
55
65
  const DEFAULT_TEMPERATURE = 0.1;
56
66
  const DEFAULT_NETWORK = 'testnet';
57
67
  const DEFAULT_OPERATIONAL_MODE: AgentOperationalMode = 'autonomous';
@@ -74,8 +84,19 @@ export interface ConversationalAgentOptions {
74
84
  mirrorNodeConfig?: MirrorNodeConfig;
75
85
  disableLogging?: boolean;
76
86
  enabledPlugins?: string[];
87
+ disabledPlugins?: string[];
77
88
  toolFilter?: (tool: { name: string; namespace?: string }) => boolean;
78
89
  mcpServers?: MCPServerConfig[];
90
+ walletExecutor?: (
91
+ base64: string,
92
+ network: 'mainnet' | 'testnet'
93
+ ) => Promise<{ transactionId: string }>;
94
+ /** Optional: provide a signer factory to override default signer selection */
95
+ customSignerFactory?: (args: {
96
+ operationalMode: AgentOperationalMode;
97
+ accountId: string;
98
+ network: NetworkType;
99
+ }) => AbstractSigner;
79
100
 
80
101
  /** Enable automatic entity memory functionality (default: true) */
81
102
  entityMemoryEnabled?: boolean;
@@ -114,6 +135,7 @@ export class ConversationalAgent {
114
135
  public hcs2Plugin: HCS2Plugin;
115
136
  public inscribePlugin: InscribePlugin;
116
137
  public hbarPlugin: HbarPlugin;
138
+ public webBrowserPlugin: WebBrowserPlugin;
117
139
  public stateManager: IStateManager;
118
140
  private options: ConversationalAgentOptions;
119
141
  public logger: Logger;
@@ -131,6 +153,7 @@ export class ConversationalAgent {
131
153
  this.hcs2Plugin = new HCS2Plugin();
132
154
  this.inscribePlugin = new InscribePlugin();
133
155
  this.hbarPlugin = new HbarPlugin();
156
+ this.webBrowserPlugin = new WebBrowserPlugin();
134
157
  this.logger = new Logger({
135
158
  module: 'ConversationalAgent',
136
159
  silent: options.disableLogging || false,
@@ -148,14 +171,18 @@ export class ConversationalAgent {
148
171
  );
149
172
  this.logger.info('Entity memory initialized');
150
173
 
151
- const provider = options.entityMemoryProvider || options.llmProvider || 'openai';
152
- const modelName =
153
- options.entityMemoryModelName ||
154
- (provider === 'anthropic'
155
- ? 'claude-3-7-sonnet-latest'
156
- : provider === 'openrouter'
157
- ? 'openai/gpt-4o-mini'
158
- : 'gpt-4o-mini');
174
+ const provider =
175
+ options.entityMemoryProvider || options.llmProvider || 'openai';
176
+ let modelName = options.entityMemoryModelName;
177
+ if (!modelName) {
178
+ if (provider === 'anthropic') {
179
+ modelName = DEFAULT_CLAUDE_MODEL;
180
+ } else if (provider === 'openrouter') {
181
+ modelName = DEFAULT_OPENROUTER_MODEL;
182
+ } else {
183
+ modelName = DEFAULT_OPENAI_MODEL;
184
+ }
185
+ }
159
186
 
160
187
  let resolverLLM: ChatOpenAI | ChatAnthropic;
161
188
  if (provider === 'anthropic') {
@@ -165,7 +192,8 @@ export class ConversationalAgent {
165
192
  temperature: 0,
166
193
  });
167
194
  } else if (provider === 'openrouter') {
168
- const baseURL = options.openRouterBaseURL || 'https://openrouter.ai/api/v1';
195
+ const baseURL =
196
+ options.openRouterBaseURL || 'https://openrouter.ai/api/v1';
169
197
  const apiKey = options.openRouterApiKey || options.openAIApiKey;
170
198
  resolverLLM = new ChatOpenAI({
171
199
  apiKey,
@@ -174,8 +202,12 @@ export class ConversationalAgent {
174
202
  configuration: {
175
203
  baseURL,
176
204
  defaultHeaders: {
177
- 'HTTP-Referer': process.env.OPENROUTER_REFERRER || 'https://hashgraphonline.com',
178
- 'X-Title': process.env.OPENROUTER_TITLE || 'Hashgraph Online Conversational Agent',
205
+ 'HTTP-Referer':
206
+ process.env.OPENROUTER_REFERRER ||
207
+ 'https://hashgraphonline.com',
208
+ 'X-Title':
209
+ process.env.OPENROUTER_TITLE ||
210
+ 'Hashgraph Online Conversational Agent',
179
211
  },
180
212
  },
181
213
  });
@@ -210,29 +242,213 @@ export class ConversationalAgent {
210
242
  this.validateOptions(accountId, privateKey);
211
243
 
212
244
  try {
213
- const serverSigner = new ServerSigner(
214
- accountId!,
215
- privateKey!,
216
- network as MirrorNetwork
217
- );
245
+ const opMode = (this.options.operationalMode ||
246
+ DEFAULT_OPERATIONAL_MODE) as string;
247
+ const bytesMode = opMode !== 'autonomous';
248
+ let signer: AbstractSigner;
249
+
250
+ try {
251
+ type InscriberBuilderWithWalletMethods = typeof InscriberBuilder & {
252
+ setPreferWalletOnly?: (prefer: boolean) => void;
253
+ setWalletInfoResolver?: (
254
+ fn: () => Promise<{ accountId: string; network: string } | null>
255
+ ) => void;
256
+ setWalletExecutor?: (
257
+ fn: (
258
+ base64: string,
259
+ network: 'mainnet' | 'testnet'
260
+ ) => Promise<{ transactionId: string }>
261
+ ) => void;
262
+ setStartInscriptionDelegate?: (
263
+ fn: (
264
+ request: Record<string, unknown>,
265
+ network: 'mainnet' | 'testnet'
266
+ ) => Promise<unknown>
267
+ ) => void;
268
+ };
269
+ const IB = InscriberBuilder as InscriberBuilderWithWalletMethods;
270
+ if (typeof IB.setPreferWalletOnly === 'function') {
271
+ IB.setPreferWalletOnly(false);
272
+ }
273
+ } catch (e) {
274
+ this.logger.warn('Failed to set wallet-only preference', e as Error);
275
+ }
276
+ if (!bytesMode) {
277
+ signer = new ServerSigner(
278
+ accountId!,
279
+ privateKey!,
280
+ network as MirrorNetwork
281
+ );
282
+ } else {
283
+ const chain: 'mainnet' | 'testnet' =
284
+ String(network || 'testnet') === 'mainnet' ? 'mainnet' : 'testnet';
285
+ const effectiveAccount = (this.options.userAccountId || accountId)!;
286
+ signer = new BrowserSigner(
287
+ effectiveAccount,
288
+ chain,
289
+ this.options.walletExecutor
290
+ );
291
+ }
292
+
293
+ this.logger.info('Signer configured', {
294
+ operationalMode: opMode,
295
+ bytesMode,
296
+ signerClass:
297
+ Object.getPrototypeOf(signer)?.constructor?.name || 'unknown',
298
+ });
299
+
300
+ try {
301
+ const bridge = getWalletBridgeProvider();
302
+ if (bridge) {
303
+ type InscriberBuilderWithWalletMethods = typeof InscriberBuilder & {
304
+ setWalletInfoResolver?: (
305
+ fn: () => Promise<{ accountId: string; network: string } | null>
306
+ ) => void;
307
+ setWalletExecutor?: (
308
+ fn: (
309
+ base64: string,
310
+ network: 'mainnet' | 'testnet'
311
+ ) => Promise<{ transactionId: string }>
312
+ ) => void;
313
+ setStartInscriptionDelegate?: (
314
+ fn: (
315
+ request: Record<string, unknown>,
316
+ network: 'mainnet' | 'testnet'
317
+ ) => Promise<unknown>
318
+ ) => void;
319
+ };
320
+ const IB = InscriberBuilder as InscriberBuilderWithWalletMethods;
321
+ if (typeof IB.setWalletInfoResolver === 'function') {
322
+ IB.setWalletInfoResolver(async () => {
323
+ const status = await bridge.status();
324
+ if (status.connected && status.accountId && status.network) {
325
+ return { accountId: status.accountId, network: status.network };
326
+ }
327
+ return null;
328
+ });
329
+ }
330
+ if (typeof IB.setWalletExecutor === 'function') {
331
+ IB.setWalletExecutor(
332
+ async (base64: string, network: 'mainnet' | 'testnet') => {
333
+ return await bridge.executeBytes(base64, network);
334
+ }
335
+ );
336
+ }
337
+ if (
338
+ typeof IB.setStartInscriptionDelegate === 'function' &&
339
+ bridge.startInscription
340
+ ) {
341
+ IB.setStartInscriptionDelegate(
342
+ async (
343
+ request: Record<string, unknown>,
344
+ network: 'mainnet' | 'testnet'
345
+ ) => {
346
+ return await bridge.startInscription!(request, network);
347
+ }
348
+ );
349
+ }
350
+
351
+ try {
352
+ type HCSOp =
353
+ | 'submitConnectionRequest'
354
+ | 'handleConnectionRequest'
355
+ | 'sendMessage'
356
+ | 'hcs2.createRegistry'
357
+ | 'hcs2.migrateRegistry'
358
+ | 'hcs2.registerEntry'
359
+ | 'hcs2.updateEntry'
360
+ | 'hcs2.deleteEntry'
361
+ | 'hcs2.submitMessage'
362
+ | 'hcs6.createRegistry'
363
+ | 'hcs6.registerEntry'
364
+ | 'hcs6.submitMessage';
365
+ type WalletBridgeProviderExt = ReturnType<
366
+ typeof getWalletBridgeProvider
367
+ > & {
368
+ startHCS?: (
369
+ op: HCSOp,
370
+ request: Record<string, unknown>,
371
+ network: 'mainnet' | 'testnet'
372
+ ) => Promise<{ transactionBytes: string }>;
373
+ };
374
+
375
+ const status = await bridge.status();
376
+ const enforceWallet = !!(bytesMode && status.connected);
377
+
378
+ SignerProviderRegistry.setWalletInfoResolver(async () => {
379
+ const s = await bridge.status();
380
+ if (s.connected && s.accountId && s.network) {
381
+ return {
382
+ accountId: s.accountId,
383
+ network: s.network as 'mainnet' | 'testnet',
384
+ };
385
+ }
386
+ return null;
387
+ });
388
+
389
+ SignerProviderRegistry.setWalletExecutor(
390
+ async (base64: string, network: 'mainnet' | 'testnet') => {
391
+ return await bridge.executeBytes(base64, network);
392
+ }
393
+ );
394
+
395
+ const extended = bridge as WalletBridgeProviderExt;
396
+ if (typeof extended?.startHCS === 'function') {
397
+ SignerProviderRegistry.setStartHCSDelegate(
398
+ async (op, request, network) => {
399
+ return await extended.startHCS!(
400
+ op as HCSOp,
401
+ request,
402
+ network
403
+ );
404
+ }
405
+ );
406
+ } else {
407
+ SignerProviderRegistry.setStartHCSDelegate(null);
408
+ }
409
+
410
+ SignerProviderRegistry.setPreferWalletOnly(enforceWallet);
411
+
412
+ type InscriberBuilderWithWalletMethods = typeof InscriberBuilder & {
413
+ setPreferWalletOnly?: (prefer: boolean) => void;
414
+ };
415
+ const IB2 = InscriberBuilder as InscriberBuilderWithWalletMethods;
416
+ if (typeof IB2.setPreferWalletOnly === 'function') {
417
+ IB2.setPreferWalletOnly(enforceWallet);
418
+ }
419
+ } catch (sakWireErr) {
420
+ this.logger.warn(
421
+ 'Failed to wire SAK SignerProviderRegistry wallet delegates',
422
+ sakWireErr as Error
423
+ );
424
+ }
425
+ }
426
+ } catch (e) {
427
+ this.logger.warn(
428
+ 'Failed to register wallet bridge providers',
429
+ e as Error
430
+ );
431
+ }
218
432
 
219
433
  let llm: ChatOpenAI | ChatAnthropic;
220
434
  let providerInfo: Record<string, unknown> = { provider: llmProvider };
221
435
  if (llmProvider === 'anthropic') {
222
436
  llm = new ChatAnthropic({
223
437
  apiKey: openAIApiKey,
224
- model: openAIModelName || 'claude-3-7-sonnet-latest',
438
+ model: openAIModelName || DEFAULT_CLAUDE_MODEL,
225
439
  temperature: DEFAULT_TEMPERATURE,
226
440
  });
227
441
  providerInfo = {
228
442
  ...providerInfo,
229
- model: openAIModelName || 'claude-3-7-sonnet-latest',
443
+ model: openAIModelName || DEFAULT_CLAUDE_MODEL,
230
444
  keyPresent: !!openAIApiKey,
231
445
  };
232
446
  } else if (llmProvider === 'openrouter') {
233
- const baseURL = this.options.openRouterBaseURL || 'https://openrouter.ai/api/v1';
447
+ const baseURL =
448
+ this.options.openRouterBaseURL || 'https://openrouter.ai/api/v1';
234
449
  const apiKey = this.options.openRouterApiKey || openAIApiKey;
235
- const modelName = openAIModelName || 'anthropic/claude-3-haiku-20240307';
450
+ const modelName =
451
+ openAIModelName || 'anthropic/claude-3-haiku-20240307';
236
452
  llm = new ChatOpenAI({
237
453
  apiKey,
238
454
  model: modelName,
@@ -240,8 +456,12 @@ export class ConversationalAgent {
240
456
  configuration: {
241
457
  baseURL,
242
458
  defaultHeaders: {
243
- 'HTTP-Referer': process.env.OPENROUTER_REFERRER || 'https://hashgraphonline.com',
244
- 'X-Title': process.env.OPENROUTER_TITLE || 'Hashgraph Online Conversational Agent',
459
+ 'HTTP-Referer':
460
+ process.env.OPENROUTER_REFERRER ||
461
+ 'https://hashgraphonline.com',
462
+ 'X-Title':
463
+ process.env.OPENROUTER_TITLE ||
464
+ 'Hashgraph Online Conversational Agent',
245
465
  },
246
466
  },
247
467
  });
@@ -252,20 +472,20 @@ export class ConversationalAgent {
252
472
  keyPresent: !!apiKey,
253
473
  };
254
474
  } else {
255
- const modelName = openAIModelName || 'gpt-4o-mini';
475
+ const modelName2 = openAIModelName || DEFAULT_OPENAI_MODEL;
256
476
  const isGPT5Model =
257
- modelName.toLowerCase().includes('gpt-5') ||
258
- modelName.toLowerCase().includes('gpt5');
477
+ modelName2.toLowerCase().includes('gpt-5') ||
478
+ modelName2.toLowerCase().includes('gpt5');
259
479
  llm = new ChatOpenAI({
260
480
  apiKey: openAIApiKey,
261
- model: modelName,
481
+ model: modelName2,
262
482
  ...(isGPT5Model
263
483
  ? { temperature: 1 }
264
484
  : { temperature: DEFAULT_TEMPERATURE }),
265
485
  });
266
486
  providerInfo = {
267
487
  ...providerInfo,
268
- model: modelName,
488
+ model: modelName2,
269
489
  keyPresent: !!openAIApiKey,
270
490
  };
271
491
  }
@@ -275,7 +495,11 @@ export class ConversationalAgent {
275
495
  this.logger.info('Preparing plugins...');
276
496
  const allPlugins = this.preparePlugins();
277
497
  this.logger.info('Creating agent config...');
278
- const agentConfig = this.createAgentConfig(serverSigner, llm, allPlugins);
498
+ const agentConfig = this.createAgentConfig(
499
+ signer as ServerSigner,
500
+ llm,
501
+ allPlugins
502
+ );
279
503
 
280
504
  this.logger.info('Creating agent...');
281
505
  this.agent = createAgent(agentConfig);
@@ -472,8 +696,14 @@ export class ConversationalAgent {
472
696
  * @throws {Error} If required fields are missing
473
697
  */
474
698
  private validateOptions(accountId?: string, privateKey?: string): void {
475
- if (!accountId || !privateKey) {
476
- throw new Error('Account ID and private key are required');
699
+ const opMode = (this.options.operationalMode ||
700
+ DEFAULT_OPERATIONAL_MODE) as string;
701
+ const bytesMode = opMode !== 'autonomous';
702
+ if (!accountId) {
703
+ throw new Error('Account ID is required');
704
+ }
705
+ if (!privateKey && !bytesMode) {
706
+ throw new Error('Private key is required in autonomous mode');
477
707
  }
478
708
 
479
709
  if (typeof accountId !== 'string') {
@@ -482,15 +712,18 @@ export class ConversationalAgent {
482
712
  );
483
713
  }
484
714
 
485
- if (typeof privateKey !== 'string') {
715
+ if (!bytesMode && typeof privateKey !== 'string') {
486
716
  throw new Error(
487
717
  `Private key must be a string, received ${typeof privateKey}: ${JSON.stringify(
488
718
  privateKey
489
719
  )}`
490
720
  );
491
721
  }
492
-
493
- if (privateKey.length < 10) {
722
+ if (
723
+ !bytesMode &&
724
+ typeof privateKey === 'string' &&
725
+ privateKey.length < 10
726
+ ) {
494
727
  throw new Error('Private key appears to be invalid (too short)');
495
728
  }
496
729
  }
@@ -501,38 +734,46 @@ export class ConversationalAgent {
501
734
  * @returns Array of plugins to initialize with the agent
502
735
  */
503
736
  private preparePlugins(): BasePlugin[] {
504
- const { additionalPlugins = [], enabledPlugins } = this.options;
737
+ const { additionalPlugins = [], enabledPlugins, disabledPlugins } = this.options;
505
738
 
506
- const standardPlugins = [
739
+ const standardPlugins: BasePlugin[] = [
507
740
  this.hcs10Plugin,
508
741
  this.hcs2Plugin,
509
742
  this.inscribePlugin,
510
743
  this.hbarPlugin,
511
744
  ];
745
+ standardPlugins.push(this.webBrowserPlugin);
512
746
 
513
747
  const corePlugins = getAllHederaCorePlugins();
748
+ let pluginPool = [...standardPlugins, ...corePlugins];
514
749
 
515
750
  if (enabledPlugins) {
516
751
  const enabledSet = new Set(enabledPlugins);
517
- const filteredPlugins = [...standardPlugins, ...corePlugins].filter(
518
- (plugin) => enabledSet.has(plugin.id)
519
- );
520
- return [...filteredPlugins, ...additionalPlugins];
752
+ pluginPool = pluginPool.filter((plugin) => enabledSet.has(plugin.id));
753
+ }
754
+
755
+ if (disabledPlugins && disabledPlugins.length > 0) {
756
+ const disabledSet = new Set(disabledPlugins);
757
+ pluginPool = pluginPool.filter((plugin) => !disabledSet.has(plugin.id));
521
758
  }
522
759
 
523
- return [...standardPlugins, ...corePlugins, ...additionalPlugins];
760
+ const additional = disabledPlugins && disabledPlugins.length > 0
761
+ ? additionalPlugins.filter((plugin) => !disabledPlugins.includes(plugin.id))
762
+ : additionalPlugins;
763
+
764
+ return [...pluginPool, ...additional];
524
765
  }
525
766
 
526
767
  /**
527
768
  * Creates the agent configuration object.
528
769
  *
529
- * @param serverSigner - The server signer instance
770
+ * @param signer - The signer instance
530
771
  * @param llm - The language model instance
531
772
  * @param allPlugins - Array of plugins to use
532
773
  * @returns Configuration object for creating the agent
533
774
  */
534
775
  private createAgentConfig(
535
- serverSigner: ServerSigner,
776
+ signer: ServerSigner,
536
777
  llm: ChatOpenAI | ChatAnthropic,
537
778
  allPlugins: BasePlugin[]
538
779
  ): Parameters<typeof createAgent>[0] {
@@ -550,7 +791,7 @@ export class ConversationalAgent {
550
791
 
551
792
  return {
552
793
  framework: 'langchain',
553
- signer: serverSigner,
794
+ signer,
554
795
  execution: {
555
796
  mode: operationalMode === 'autonomous' ? 'direct' : 'bytes',
556
797
  operationalMode: operationalMode,
@@ -820,7 +1061,7 @@ export class ConversationalAgent {
820
1061
  }
821
1062
  if (typeof response === 'string') {
822
1063
  const match = response.match(
823
- /transaction[\s\w]*ID[\s:"]*([0-9a-fA-F@\.\-]+)/i
1064
+ /transaction[\s\w]*ID[\s:"]*([0-9a-fA-F@._-]+)/i
824
1065
  );
825
1066
  return match ? match[1] : undefined;
826
1067
  }
@@ -902,6 +1143,38 @@ export class ConversationalAgent {
902
1143
  }
903
1144
  }
904
1145
 
1146
+ /**
1147
+ * Switch operational mode
1148
+ */
1149
+ switchMode(mode?: AgentOperationalMode): void {
1150
+ if (this.agent?.switchMode) {
1151
+ this.agent.switchMode(mode || 'autonomous');
1152
+ }
1153
+ }
1154
+
1155
+ /**
1156
+ * Get usage statistics
1157
+ */
1158
+ getUsageStats(): unknown {
1159
+ return this.agent?.getUsageStats?.() ?? {};
1160
+ }
1161
+
1162
+ /**
1163
+ * Clear usage statistics
1164
+ */
1165
+ clearUsageStats(): void {
1166
+ if (this.agent?.clearUsageStats) {
1167
+ this.agent.clearUsageStats();
1168
+ }
1169
+ }
1170
+
1171
+ /**
1172
+ * Shutdown the agent
1173
+ */
1174
+ shutdown(): Promise<void> {
1175
+ return this.agent?.shutdown?.() ?? Promise.resolve();
1176
+ }
1177
+
905
1178
  private extractResponseText(response: unknown): string {
906
1179
  if (typeof response === 'string') {
907
1180
  return response;
@@ -6,6 +6,13 @@ import {
6
6
  wrapToolWithFormValidation,
7
7
  } from '../langchain/form-validating-tool-wrapper';
8
8
  import { FormGenerator } from '../forms/form-generator';
9
+ import {
10
+ fieldGuidanceRegistry,
11
+ } from '../forms/field-guidance-registry';
12
+ import type {
13
+ ToolFieldConfiguration as FG_ToolFieldConfiguration,
14
+ FieldGuidanceProvider as FG_FieldGuidanceProvider,
15
+ } from '../forms/field-guidance-registry';
9
16
  import { isFormValidatable } from '@hashgraphonline/standards-agent-kit';
10
17
 
11
18
  /**
@@ -40,6 +47,8 @@ export interface ToolMetadata {
40
47
  dependencies: string[];
41
48
  schema: unknown;
42
49
  entityResolutionPreferences?: EntityResolutionPreferences;
50
+ fieldGuidance?: FG_ToolFieldConfiguration;
51
+ fieldGuidanceProvider?: FG_FieldGuidanceProvider;
43
52
  }
44
53
 
45
54
  /**
@@ -50,6 +59,12 @@ export interface ToolRegistryEntry {
50
59
  metadata: ToolMetadata;
51
60
  wrapper?: FormValidatingToolWrapper<z.ZodObject<z.ZodRawShape>> | undefined;
52
61
  originalTool: StructuredTool;
62
+ options?: {
63
+ priority?: ToolCapabilities['priority'];
64
+ capability?: string;
65
+ enabled?: boolean;
66
+ namespace?: string;
67
+ };
53
68
  }
54
69
 
55
70
  /**
@@ -188,9 +203,30 @@ export class ToolRegistry {
188
203
  metadata,
189
204
  wrapper,
190
205
  originalTool: tool,
206
+ options: {
207
+ priority: capabilities.priority,
208
+ capability: 'basic', // Default capability
209
+ enabled: true, // All tools are enabled by default
210
+ namespace: metadata.category,
211
+ },
191
212
  };
192
213
 
193
214
  this.tools.set(tool.name, entry);
215
+
216
+ try {
217
+ const metaFG = metadata.fieldGuidance as FG_ToolFieldConfiguration | undefined;
218
+ if (metaFG) {
219
+ fieldGuidanceRegistry.registerToolConfiguration(metaFG);
220
+ }
221
+ const provider = metadata.fieldGuidanceProvider as FG_FieldGuidanceProvider | undefined;
222
+ if (provider) {
223
+ const pattern = metaFG?.toolPattern ?? tool.name;
224
+ fieldGuidanceRegistry.registerToolProvider(pattern, provider, {
225
+ id: `${tool.name}:field-guidance-provider`,
226
+ priority: 0,
227
+ });
228
+ }
229
+ } catch {}
194
230
  }
195
231
 
196
232
  /**
@@ -279,6 +315,55 @@ export class ToolRegistry {
279
315
  return Array.from(this.tools.keys());
280
316
  }
281
317
 
318
+ /**
319
+ * Get tools by priority
320
+ */
321
+ getToolsByPriority(priority: ToolCapabilities['priority']): ToolRegistryEntry[] {
322
+ return this.getToolsByCapability('priority', priority);
323
+ }
324
+
325
+ /**
326
+ * Get enabled tools (all tools are considered enabled by default)
327
+ */
328
+ getEnabledTools(): ToolRegistryEntry[] {
329
+ return this.getAllRegistryEntries();
330
+ }
331
+
332
+ /**
333
+ * Get tools by namespace/category
334
+ */
335
+ getToolsByNamespace(namespace?: string): ToolRegistryEntry[] {
336
+ if (!namespace) {
337
+ return this.getAllRegistryEntries();
338
+ }
339
+ return this.getToolsByQuery({ category: namespace as ToolMetadata['category'] });
340
+ }
341
+
342
+ /**
343
+ * Check if registry has capability
344
+ */
345
+ hasCapability(capability: keyof ToolCapabilities): boolean {
346
+ for (const entry of this.tools.values()) {
347
+ if (entry.metadata.capabilities[capability]) {
348
+ return true;
349
+ }
350
+ }
351
+ return false;
352
+ }
353
+
354
+ /**
355
+ * Update tool options (metadata)
356
+ */
357
+ updateToolOptions(name: string, options: Partial<ToolMetadata>): boolean {
358
+ const entry = this.tools.get(name);
359
+ if (!entry) {
360
+ return false;
361
+ }
362
+
363
+ entry.metadata = { ...entry.metadata, ...options };
364
+ return true;
365
+ }
366
+
282
367
  /**
283
368
  * Check if a tool is registered
284
369
  */