@hashgraphonline/conversational-agent 0.2.103 → 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 (194) hide show
  1. package/README.md +64 -27
  2. package/cli/dist/CLIApp.d.ts +11 -0
  3. package/cli/dist/CLIApp.d.ts.map +1 -0
  4. package/cli/dist/CLIApp.js +128 -0
  5. package/cli/dist/CLIApp.js.map +1 -0
  6. package/cli/dist/LocalConversationalAgent.d.ts +37 -0
  7. package/cli/dist/LocalConversationalAgent.js +58 -0
  8. package/cli/dist/app.d.ts +18 -0
  9. package/cli/dist/app.d.ts.map +1 -0
  10. package/cli/dist/app.js +14 -0
  11. package/cli/dist/app.js.map +1 -0
  12. package/cli/dist/cli.d.ts +3 -0
  13. package/cli/dist/cli.d.ts.map +1 -0
  14. package/cli/dist/cli.js +87 -0
  15. package/cli/dist/cli.js.map +1 -0
  16. package/cli/dist/components/AppContainer.d.ts +16 -0
  17. package/cli/dist/components/AppContainer.js +24 -0
  18. package/cli/dist/components/AppScreens.d.ts +2 -0
  19. package/cli/dist/components/AppScreens.js +259 -0
  20. package/cli/dist/components/ChatScreen.d.ts +21 -0
  21. package/cli/dist/components/ChatScreen.d.ts.map +1 -0
  22. package/cli/dist/components/ChatScreen.js +40 -0
  23. package/cli/dist/components/ChatScreen.js.map +1 -0
  24. package/cli/dist/components/DebugLoadingScreen.d.ts +5 -0
  25. package/cli/dist/components/DebugLoadingScreen.js +31 -0
  26. package/cli/dist/components/LoadingScreen.d.ts +3 -0
  27. package/cli/dist/components/LoadingScreen.d.ts.map +1 -0
  28. package/cli/dist/components/LoadingScreen.js +17 -0
  29. package/cli/dist/components/LoadingScreen.js.map +1 -0
  30. package/cli/dist/components/LoadingScreenDebug.d.ts +5 -0
  31. package/cli/dist/components/LoadingScreenDebug.js +27 -0
  32. package/cli/dist/components/MCPConfigScreen.d.ts +28 -0
  33. package/cli/dist/components/MCPConfigScreen.d.ts.map +1 -0
  34. package/cli/dist/components/MCPConfigScreen.js +186 -0
  35. package/cli/dist/components/MCPConfigScreen.js.map +1 -0
  36. package/cli/dist/components/ScreenRouter.d.ts +13 -0
  37. package/cli/dist/components/ScreenRouter.d.ts.map +1 -0
  38. package/cli/dist/components/ScreenRouter.js +23 -0
  39. package/cli/dist/components/ScreenRouter.js.map +1 -0
  40. package/cli/dist/components/SetupScreen.d.ts +16 -0
  41. package/cli/dist/components/SetupScreen.d.ts.map +1 -0
  42. package/cli/dist/components/SetupScreen.js +67 -0
  43. package/cli/dist/components/SetupScreen.js.map +1 -0
  44. package/cli/dist/components/SingleLoadingScreen.d.ts +5 -0
  45. package/cli/dist/components/SingleLoadingScreen.js +27 -0
  46. package/cli/dist/components/StatusBadge.d.ts +10 -0
  47. package/cli/dist/components/StatusBadge.d.ts.map +1 -0
  48. package/cli/dist/components/StatusBadge.js +24 -0
  49. package/cli/dist/components/StatusBadge.js.map +1 -0
  50. package/cli/dist/components/TerminalWindow.d.ts +9 -0
  51. package/cli/dist/components/TerminalWindow.d.ts.map +1 -0
  52. package/cli/dist/components/TerminalWindow.js +19 -0
  53. package/cli/dist/components/TerminalWindow.js.map +1 -0
  54. package/cli/dist/components/WelcomeScreen.d.ts +12 -0
  55. package/cli/dist/components/WelcomeScreen.d.ts.map +1 -0
  56. package/cli/dist/components/WelcomeScreen.js +47 -0
  57. package/cli/dist/components/WelcomeScreen.js.map +1 -0
  58. package/cli/dist/context/AppContext.d.ts +68 -0
  59. package/cli/dist/context/AppContext.js +363 -0
  60. package/cli/dist/headless-runner.d.ts +17 -0
  61. package/cli/dist/headless-runner.d.ts.map +1 -0
  62. package/cli/dist/headless-runner.js +128 -0
  63. package/cli/dist/headless-runner.js.map +1 -0
  64. package/cli/dist/hooks/useInitializeAgent.d.ts +19 -0
  65. package/cli/dist/hooks/useInitializeAgent.d.ts.map +1 -0
  66. package/cli/dist/hooks/useInitializeAgent.js +29 -0
  67. package/cli/dist/hooks/useInitializeAgent.js.map +1 -0
  68. package/cli/dist/hooks/useStableState.d.ts +38 -0
  69. package/cli/dist/hooks/useStableState.d.ts.map +1 -0
  70. package/cli/dist/hooks/useStableState.js +69 -0
  71. package/cli/dist/hooks/useStableState.js.map +1 -0
  72. package/cli/dist/managers/AgentManager.d.ts +58 -0
  73. package/cli/dist/managers/AgentManager.d.ts.map +1 -0
  74. package/cli/dist/managers/AgentManager.js +121 -0
  75. package/cli/dist/managers/AgentManager.js.map +1 -0
  76. package/cli/dist/managers/ConfigManager.d.ts +54 -0
  77. package/cli/dist/managers/ConfigManager.d.ts.map +1 -0
  78. package/cli/dist/managers/ConfigManager.js +188 -0
  79. package/cli/dist/managers/ConfigManager.js.map +1 -0
  80. package/cli/dist/types.d.ts +52 -0
  81. package/cli/dist/types.d.ts.map +1 -0
  82. package/cli/dist/types.js +34 -0
  83. package/cli/dist/types.js.map +1 -0
  84. package/dist/cjs/config/system-message.d.ts +1 -1
  85. package/dist/cjs/conversational-agent.d.ts +30 -2
  86. package/dist/cjs/core/tool-registry.d.ts +29 -0
  87. package/dist/cjs/forms/field-guidance-registry.d.ts +33 -0
  88. package/dist/cjs/index.cjs +1 -1
  89. package/dist/cjs/index.cjs.map +1 -1
  90. package/dist/cjs/index.d.ts +1 -0
  91. package/dist/cjs/mcp/types.d.ts +14 -3
  92. package/dist/cjs/plugins/index.d.ts +1 -0
  93. package/dist/cjs/plugins/inscribe/InscribePlugin.d.ts +1 -0
  94. package/dist/cjs/plugins/web-browser/WebBrowserPlugin.d.ts +14 -0
  95. package/dist/cjs/runtime/wallet-bridge.d.ts +26 -0
  96. package/dist/cjs/services/attachment-processor.d.ts +1 -2
  97. package/dist/cjs/services/content-store-manager.d.ts +1 -1
  98. package/dist/cjs/services/formatters/types.d.ts +3 -1
  99. package/dist/cjs/services/index.d.ts +1 -1
  100. package/dist/cjs/signers/browser-signer.d.ts +32 -0
  101. package/dist/esm/index.js +3 -0
  102. package/dist/esm/index.js.map +1 -1
  103. package/dist/esm/index10.js +13 -5
  104. package/dist/esm/index10.js.map +1 -1
  105. package/dist/esm/index13.js +157 -179
  106. package/dist/esm/index13.js.map +1 -1
  107. package/dist/esm/index15.js +9 -4
  108. package/dist/esm/index15.js.map +1 -1
  109. package/dist/esm/index18.js.map +1 -1
  110. package/dist/esm/index2.js +25 -27
  111. package/dist/esm/index2.js.map +1 -1
  112. package/dist/esm/index21.js +1 -1
  113. package/dist/esm/index21.js.map +1 -1
  114. package/dist/esm/index23.js +3 -3
  115. package/dist/esm/index24.js.map +1 -1
  116. package/dist/esm/index26.js.map +1 -1
  117. package/dist/esm/index3.js.map +1 -1
  118. package/dist/esm/index30.js.map +1 -1
  119. package/dist/esm/index31.js +6 -3
  120. package/dist/esm/index31.js.map +1 -1
  121. package/dist/esm/index33.js +5 -5
  122. package/dist/esm/index33.js.map +1 -1
  123. package/dist/esm/index36.js +8 -45
  124. package/dist/esm/index36.js.map +1 -1
  125. package/dist/esm/index37.js +41 -102
  126. package/dist/esm/index37.js.map +1 -1
  127. package/dist/esm/index38.js +107 -21
  128. package/dist/esm/index38.js.map +1 -1
  129. package/dist/esm/index39.js +66 -12
  130. package/dist/esm/index39.js.map +1 -1
  131. package/dist/esm/index4.js +43 -0
  132. package/dist/esm/index4.js.map +1 -1
  133. package/dist/esm/index40.js +79 -7
  134. package/dist/esm/index40.js.map +1 -1
  135. package/dist/esm/index41.js +21 -5
  136. package/dist/esm/index41.js.map +1 -1
  137. package/dist/esm/index42.js +5 -255
  138. package/dist/esm/index42.js.map +1 -1
  139. package/dist/esm/index43.js +12 -184
  140. package/dist/esm/index43.js.map +1 -1
  141. package/dist/esm/index44.js +309 -79
  142. package/dist/esm/index44.js.map +1 -1
  143. package/dist/esm/index45.js +181 -24
  144. package/dist/esm/index45.js.map +1 -1
  145. package/dist/esm/index46.js +30 -0
  146. package/dist/esm/index46.js.map +1 -0
  147. package/dist/esm/index47.js +10 -0
  148. package/dist/esm/index47.js.map +1 -0
  149. package/dist/esm/index48.js +98 -0
  150. package/dist/esm/index48.js.map +1 -0
  151. package/dist/esm/index5.js +2 -2
  152. package/dist/esm/index6.js +231 -52
  153. package/dist/esm/index6.js.map +1 -1
  154. package/dist/types/config/system-message.d.ts +1 -1
  155. package/dist/types/conversational-agent.d.ts +30 -2
  156. package/dist/types/core/tool-registry.d.ts +29 -0
  157. package/dist/types/forms/field-guidance-registry.d.ts +33 -0
  158. package/dist/types/index.d.ts +1 -0
  159. package/dist/types/mcp/types.d.ts +14 -3
  160. package/dist/types/plugins/index.d.ts +1 -0
  161. package/dist/types/plugins/inscribe/InscribePlugin.d.ts +1 -0
  162. package/dist/types/plugins/web-browser/WebBrowserPlugin.d.ts +14 -0
  163. package/dist/types/runtime/wallet-bridge.d.ts +26 -0
  164. package/dist/types/services/attachment-processor.d.ts +1 -2
  165. package/dist/types/services/content-store-manager.d.ts +1 -1
  166. package/dist/types/services/formatters/types.d.ts +3 -1
  167. package/dist/types/services/index.d.ts +1 -1
  168. package/dist/types/signers/browser-signer.d.ts +32 -0
  169. package/package.json +40 -37
  170. package/src/config/system-message.ts +3 -3
  171. package/src/conversational-agent.ts +356 -61
  172. package/src/core/tool-registry.ts +85 -0
  173. package/src/forms/field-guidance-registry.ts +213 -188
  174. package/src/forms/form-generator.ts +28 -12
  175. package/src/index.ts +1 -0
  176. package/src/langchain/form-aware-agent-executor.ts +6 -6
  177. package/src/langchain/langchain-agent.ts +1 -1
  178. package/src/mcp/mcp-client-manager.ts +12 -5
  179. package/src/mcp/types.ts +15 -3
  180. package/src/memory/content-storage.ts +19 -6
  181. package/src/memory/smart-memory-manager.ts +0 -1
  182. package/src/plugins/hbar/AccountBuilder.ts +16 -16
  183. package/src/plugins/hcs-10/HCS10Plugin.ts +38 -38
  184. package/src/plugins/hcs-2/HCS2Plugin.ts +2 -2
  185. package/src/plugins/index.ts +2 -1
  186. package/src/plugins/inscribe/InscribePlugin.ts +46 -2
  187. package/src/plugins/web-browser/WebBrowserPlugin.ts +128 -0
  188. package/src/runtime/wallet-bridge.ts +46 -0
  189. package/src/services/attachment-processor.ts +1 -1
  190. package/src/services/content-store-manager.ts +1 -1
  191. package/src/services/formatters/types.ts +3 -1
  192. package/src/services/index.ts +1 -1
  193. package/src/signers/browser-signer.ts +111 -0
  194. package/cli/readme.md +0 -181
@@ -979,9 +979,11 @@ export class FormAwareAgentExecutor extends AgentExecutor {
979
979
  '🔗 HASHLINK DETECTED: Processing HashLink response separately to preserve metadata'
980
980
  );
981
981
 
982
+ const parsedRecord = parsed as Record<string, unknown>;
982
983
  responseMetadata = {
983
984
  ...responseMetadata,
984
- hashLinkBlock: (parsed as Record<string, unknown>).hashLinkBlock,
985
+ hashLinkBlock: parsedRecord.hashLinkBlock,
986
+ ...parsedRecord,
985
987
  };
986
988
 
987
989
  formattedOutput = ResponseFormatter.formatHashLinkResponse(parsed);
@@ -1003,6 +1005,7 @@ export class FormAwareAgentExecutor extends AgentExecutor {
1003
1005
  responseMetadata = {
1004
1006
  ...responseMetadata,
1005
1007
  hashLinkBlock: (parsed as Record<string, unknown>).hashLinkBlock,
1008
+ ...parsed,
1006
1009
  };
1007
1010
  }
1008
1011
  } else {
@@ -1240,6 +1243,7 @@ Please fill out the form below to continue.`;
1240
1243
  }));
1241
1244
  }
1242
1245
 
1246
+
1243
1247
  /**
1244
1248
  * Processes HashLink block responses from tools
1245
1249
  */
@@ -1251,11 +1255,7 @@ Please fill out the form below to continue.`;
1251
1255
 
1252
1256
  if (toolResponse.hashLinkBlock) {
1253
1257
  hashLinkBlock = toolResponse.hashLinkBlock;
1254
- } else if (
1255
- toolResponse.success &&
1256
- toolResponse.inscription &&
1257
- toolResponse.hashLinkBlock
1258
- ) {
1258
+ } else if (toolResponse.success && toolResponse.hashLinkBlock) {
1259
1259
  hashLinkBlock = toolResponse.hashLinkBlock;
1260
1260
  }
1261
1261
 
@@ -819,7 +819,7 @@ export class LangChainAgent extends BaseAgent {
819
819
  if (args.metaOptions && typeof args.metaOptions === 'object') {
820
820
  const metaOptions = args.metaOptions as Record<string, unknown>;
821
821
  if (metaOptions.transactionMemo) {
822
- console.warn(
822
+ this.logger.warn(
823
823
  '🚨 WORKAROUND: Stripping transactionMemo from hedera-hts-mint-nft to avoid bug',
824
824
  { originalMemo: metaOptions.transactionMemo }
825
825
  );
@@ -56,10 +56,17 @@ export class MCPClientManager {
56
56
  this.clients.set(config.name, client);
57
57
 
58
58
  const toolsResponse = await client.listTools();
59
- const toolsWithServer: MCPToolInfo[] = toolsResponse.tools.map(tool => ({
60
- ...tool,
61
- serverName: config.name,
62
- }));
59
+ const toolsWithServer: MCPToolInfo[] = toolsResponse.tools.map((tool: unknown) => {
60
+ const t = tool as { description?: string } & Record<string, unknown>;
61
+ const { description, ...rest } = t;
62
+ const base = description !== undefined && typeof description === 'string'
63
+ ? { ...rest, description }
64
+ : { ...rest };
65
+ return {
66
+ ...(base as Omit<MCPToolInfo, 'serverName'>),
67
+ serverName: config.name,
68
+ } as MCPToolInfo;
69
+ });
63
70
 
64
71
  this.tools.set(config.name, toolsWithServer);
65
72
  this.logger.info(`Connected to MCP server ${config.name} with ${toolsWithServer.length} tools`);
@@ -205,4 +212,4 @@ export class MCPClientManager {
205
212
  }
206
213
  return this.contentProcessor.analyzeResponse(response);
207
214
  }
208
- }
215
+ }
package/src/mcp/types.ts CHANGED
@@ -1,4 +1,16 @@
1
- import type { Tool } from '@modelcontextprotocol/sdk/types.js';
1
+ /**
2
+ * Minimal MCP Tool shape used internally to avoid external type dependency resolution issues.
3
+ * Aligns with MCP tool metadata returned by listTools.
4
+ */
5
+ export interface BaseMCPTool {
6
+ name: string;
7
+ description?: string;
8
+ /**
9
+ * JSON Schema describing input parameters for the tool.
10
+ * Kept as unknown and validated/converted at the boundary.
11
+ */
12
+ inputSchema?: unknown;
13
+ }
2
14
 
3
15
  export interface MCPServerConfig {
4
16
  name: string;
@@ -17,7 +29,7 @@ export interface MCPServerConfig {
17
29
  toolDescriptions?: Record<string, string>;
18
30
  }
19
31
 
20
- export interface MCPToolInfo extends Tool {
32
+ export interface MCPToolInfo extends BaseMCPTool {
21
33
  serverName: string;
22
34
  }
23
35
 
@@ -26,4 +38,4 @@ export interface MCPConnectionStatus {
26
38
  connected: boolean;
27
39
  error?: string;
28
40
  tools: MCPToolInfo[];
29
- }
41
+ }
@@ -317,7 +317,11 @@ export class ContentStorage implements ContentReferenceStore {
317
317
  * Get the current storage configuration
318
318
  * @returns Storage configuration object
319
319
  */
320
- getConfig(): { maxStorage: number; currentUsage: number; utilizationPercentage: number } {
320
+ getConfig(): {
321
+ maxStorage: number;
322
+ currentUsage: number;
323
+ utilizationPercentage: number;
324
+ } {
321
325
  return {
322
326
  maxStorage: this.maxStorage,
323
327
  currentUsage: this.messages.length,
@@ -354,11 +358,17 @@ export class ContentStorage implements ContentReferenceStore {
354
358
  * Export messages to a JSON-serializable format
355
359
  * @returns Serializable representation of stored messages
356
360
  */
357
- exportMessages(): Array<{ content: string; type: string; storedAt: string; id: string }> {
361
+ exportMessages(): Array<{
362
+ content: string;
363
+ type: string;
364
+ storedAt: string;
365
+ id: string;
366
+ }> {
358
367
  return this.messages.map((stored) => ({
359
- content: typeof stored.message.content === 'string'
360
- ? stored.message.content
361
- : JSON.stringify(stored.message.content),
368
+ content:
369
+ typeof stored.message.content === 'string'
370
+ ? stored.message.content
371
+ : JSON.stringify(stored.message.content),
362
372
  type: stored.message._getType(),
363
373
  storedAt: stored.storedAt.toISOString(),
364
374
  id: stored.id,
@@ -832,7 +842,10 @@ export class ContentStorage implements ContentReferenceStore {
832
842
  return new Date(Date.now() + policy.maxAgeMs);
833
843
  }
834
844
 
835
- private getCleanupPolicy(source: ContentSource): { maxAgeMs: number; priority: number } {
845
+ private getCleanupPolicy(source: ContentSource): {
846
+ maxAgeMs: number;
847
+ priority: number;
848
+ } {
836
849
  switch (source) {
837
850
  case 'mcp_tool':
838
851
  return this.referenceConfig.cleanupPolicies.recent;
@@ -702,7 +702,6 @@ export class SmartMemoryManager {
702
702
  }
703
703
  }
704
704
 
705
- // Merge duplicates by entityId, preferring the newest and one that carries transactionId
706
705
  const mergedById = new Map<string, EntityAssociation>();
707
706
  const getTime = (d: Date | string): number =>
708
707
  d instanceof Date ? d.getTime() : new Date(d).getTime();
@@ -1,8 +1,4 @@
1
- import {
2
- AccountId,
3
- Hbar,
4
- TransferTransaction,
5
- } from '@hashgraph/sdk';
1
+ import { AccountId, Hbar, TransferTransaction } from '@hashgraph/sdk';
6
2
  import BigNumber from 'bignumber.js';
7
3
  import { HederaAgentKit, BaseServiceBuilder } from 'hedera-agent-kit';
8
4
  import { HbarTransferParams } from './types';
@@ -24,7 +20,7 @@ export class AccountBuilder extends BaseServiceBuilder {
24
20
  ): this {
25
21
  this.clearNotes();
26
22
  const transaction = new TransferTransaction();
27
-
23
+
28
24
  if (!params.transfers || params.transfers.length === 0) {
29
25
  throw new Error('HbarTransferParams must include at least one transfer.');
30
26
  }
@@ -61,7 +57,7 @@ export class AccountBuilder extends BaseServiceBuilder {
61
57
  this.kit.userAccountId
62
58
  } to ${recipientAccountId.toString()}`
63
59
  );
64
-
60
+
65
61
  this.addNote(
66
62
  `Configured HBAR transfer from your account (${
67
63
  this.kit.userAccountId
@@ -84,7 +80,7 @@ export class AccountBuilder extends BaseServiceBuilder {
84
80
  amount: BigNumber;
85
81
  hbar: Hbar;
86
82
  }> = [];
87
-
83
+
88
84
  for (const transferInput of params.transfers) {
89
85
  const accountId =
90
86
  typeof transferInput.accountId === 'string'
@@ -99,7 +95,7 @@ export class AccountBuilder extends BaseServiceBuilder {
99
95
 
100
96
  const amountBigNum = new BigNumber(amountValue);
101
97
  const roundedAmount = amountBigNum.toFixed(8, BigNumber.ROUND_DOWN);
102
-
98
+
103
99
  this.logger.info(
104
100
  `Processing transfer: ${amountValue} HBAR (rounded to ${roundedAmount}) for account ${accountId.toString()}`
105
101
  );
@@ -108,7 +104,7 @@ export class AccountBuilder extends BaseServiceBuilder {
108
104
  processedTransfers.push({
109
105
  accountId,
110
106
  amount: amountBigNum,
111
- hbar: sdkHbarAmount
107
+ hbar: sdkHbarAmount,
112
108
  });
113
109
 
114
110
  const tinybarsContribution = sdkHbarAmount.toTinybars();
@@ -121,20 +117,24 @@ export class AccountBuilder extends BaseServiceBuilder {
121
117
  this.logger.warn(
122
118
  `Transfer sum not zero: ${netZeroInTinybars.toString()} tinybars off. Adjusting last transfer.`
123
119
  );
124
-
120
+
125
121
  if (processedTransfers.length > 0) {
126
- const lastTransfer = processedTransfers[processedTransfers.length - 1];
122
+ const lastTransfer =
123
+ processedTransfers[processedTransfers.length - 1];
127
124
  const adjustment = netZeroInTinybars.dividedBy(-100000000);
128
125
  const adjustedAmount = lastTransfer.amount.plus(adjustment);
129
- const adjustedRounded = adjustedAmount.toFixed(8, BigNumber.ROUND_DOWN);
126
+ const adjustedRounded = adjustedAmount.toFixed(
127
+ 8,
128
+ BigNumber.ROUND_DOWN
129
+ );
130
130
  lastTransfer.hbar = Hbar.fromString(adjustedRounded);
131
-
131
+
132
132
  this.logger.info(
133
133
  `Adjusted last transfer for ${lastTransfer.accountId.toString()} to ${adjustedRounded} HBAR`
134
134
  );
135
135
  }
136
136
  }
137
-
137
+
138
138
  for (const transfer of processedTransfers) {
139
139
  transaction.addHbarTransfer(transfer.accountId, transfer.hbar);
140
140
  }
@@ -151,4 +151,4 @@ export class AccountBuilder extends BaseServiceBuilder {
151
151
  this.setCurrentTransaction(transaction);
152
152
  return this;
153
153
  }
154
- }
154
+ }
@@ -19,33 +19,15 @@ import {
19
19
  AcceptConnectionRequestTool,
20
20
  RetrieveProfileTool,
21
21
  ListUnapprovedConnectionRequestsTool,
22
+ RegisteredAgent,
22
23
  } from '@hashgraphonline/standards-agent-kit';
23
24
  import { HCS10Client } from '@hashgraphonline/standards-sdk';
25
+ import { PrivateKey } from 'node_modules/@hashgraph/sdk/lib/Mnemonic';
24
26
 
25
27
  interface HCS10ClientManager {
26
28
  initializeConnectionsManager(client: HCS10Client): void;
27
29
  }
28
30
 
29
- /**
30
- * Extracts private key string from operator key
31
- */
32
- function extractPrivateKey(opKey: unknown): string {
33
- const key = opKey as {
34
- toString?: () => string;
35
- toStringRaw?: () => string;
36
- };
37
-
38
- if (typeof key?.toStringRaw === 'function') {
39
- return key.toStringRaw();
40
- }
41
-
42
- if (typeof key?.toString === 'function') {
43
- return key.toString();
44
- }
45
-
46
- return String(key);
47
- }
48
-
49
31
  function hasInitializeConnectionsManager(
50
32
  stateManager: IStateManager
51
33
  ): stateManager is IStateManager & HCS10ClientManager {
@@ -67,7 +49,7 @@ export class HCS10Plugin extends BasePlugin {
67
49
  namespace = 'hcs10';
68
50
 
69
51
  private stateManager?: IStateManager;
70
- private tools: HederaTool[] = [];
52
+ private tools: any[] = [];
71
53
  appConfig?: Record<string, unknown>;
72
54
 
73
55
  override async initialize(context: GenericPluginContext): Promise<void> {
@@ -89,17 +71,27 @@ export class HCS10Plugin extends BasePlugin {
89
71
  new OpenConvaiState();
90
72
 
91
73
  const accountId = hederaKit.signer.getAccountId().toString();
74
+ const isBytesMode =
75
+ String(hederaKit.operationalMode || 'returnBytes') === 'returnBytes';
92
76
  let inboundTopicId = '';
93
77
  let outboundTopicId = '';
94
78
 
79
+ let operatorPrivateKeyRef: PrivateKey =
80
+ hederaKit.signer.getOperatorPrivateKey();
81
+ let operatorPrivateKeySerialized: string | undefined;
82
+
95
83
  try {
96
- const opKey = hederaKit.signer.getOperatorPrivateKey();
97
- const privateKey = extractPrivateKey(opKey);
84
+ const resolved =
85
+ typeof operatorPrivateKeyRef?.toString === 'function'
86
+ ? operatorPrivateKeyRef.toString()
87
+ : '';
88
+
89
+ operatorPrivateKeySerialized = resolved;
98
90
 
99
91
  const hcs10Client = new HCS10Client({
100
92
  network: hederaKit.network as 'mainnet' | 'testnet',
101
93
  operatorId: accountId,
102
- operatorPrivateKey: privateKey,
94
+ operatorPrivateKey: operatorPrivateKeyRef,
103
95
  logLevel: 'error',
104
96
  });
105
97
 
@@ -110,52 +102,60 @@ export class HCS10Plugin extends BasePlugin {
110
102
  }
111
103
  } catch (profileError) {
112
104
  this.context.logger.warn(
113
- 'Could not retrieve profile topics:',
105
+ 'Skipping profile topic discovery',
114
106
  profileError
115
107
  );
116
108
  }
117
109
 
118
- this.stateManager.setCurrentAgent({
110
+ const agentRecord: Record<string, unknown> = {
119
111
  name: `Agent ${accountId}`,
120
112
  accountId: accountId,
121
113
  inboundTopicId,
122
114
  outboundTopicId,
123
- privateKey: ((): string => {
124
- const opKey = hederaKit.signer.getOperatorPrivateKey();
125
- return extractPrivateKey(opKey);
126
- })(),
127
- });
115
+ };
116
+ if (!isBytesMode && operatorPrivateKeySerialized) {
117
+ agentRecord.privateKey = operatorPrivateKeySerialized;
118
+ }
119
+ this.stateManager.setCurrentAgent(
120
+ agentRecord as unknown as RegisteredAgent
121
+ );
128
122
 
129
123
  this.context.logger.info(
130
124
  `Set current agent: ${accountId} with topics ${inboundTopicId}/${outboundTopicId}`
131
125
  );
132
126
 
133
- if (this.stateManager && !this.stateManager.getConnectionsManager()) {
127
+ if (
128
+ !isBytesMode &&
129
+ this.stateManager &&
130
+ !this.stateManager.getConnectionsManager()
131
+ ) {
134
132
  try {
135
- const opKey = hederaKit.signer.getOperatorPrivateKey();
136
- const privateKey = extractPrivateKey(opKey);
137
133
  const hcs10Client = new HCS10Client({
138
134
  network: hederaKit.network as 'mainnet' | 'testnet',
139
135
  operatorId: accountId,
140
- operatorPrivateKey: privateKey,
136
+ operatorPrivateKey: operatorPrivateKeyRef ?? '',
141
137
  logLevel: 'error',
142
138
  });
143
139
 
144
140
  if (hasInitializeConnectionsManager(this.stateManager)) {
145
141
  this.stateManager.initializeConnectionsManager(hcs10Client);
146
142
  } else {
147
- this.context.logger.warn('StateManager does not support connection manager initialization');
143
+ this.context.logger.warn(
144
+ 'StateManager does not support connection manager initialization'
145
+ );
148
146
  }
149
147
  this.context.logger.info(
150
148
  'ConnectionsManager initialized in HCS10Plugin'
151
149
  );
152
150
  } catch (cmError) {
153
- this.context.logger.warn('Could not initialize ConnectionsManager:', cmError);
151
+ this.context.logger.warn(
152
+ 'Could not initialize ConnectionsManager:',
153
+ cmError
154
+ );
154
155
  }
155
156
  }
156
157
 
157
158
  this.initializeTools();
158
-
159
159
  this.context.logger.info('HCS-10 Plugin initialized successfully');
160
160
  } catch (error) {
161
161
  this.context.logger.error('Failed to initialize HCS-10 plugin:', error);
@@ -26,7 +26,7 @@ export class HCS2Plugin extends BasePlugin {
26
26
  author = 'Hashgraph Online';
27
27
  namespace = 'hcs2';
28
28
 
29
- private tools: HederaTool[] = [];
29
+ private tools: any[] = [];
30
30
 
31
31
  override async initialize(context: GenericPluginContext): Promise<void> {
32
32
  await super.initialize(context);
@@ -105,4 +105,4 @@ export class HCS2Plugin extends BasePlugin {
105
105
  this.context.logger.info('HCS-2 Plugin cleaned up');
106
106
  }
107
107
  }
108
- }
108
+ }
@@ -2,4 +2,5 @@ export { HCS10Plugin } from './hcs-10';
2
2
  export { HCS2Plugin } from './hcs-2';
3
3
  export { InscribePlugin } from './inscribe';
4
4
  export { HbarPlugin } from './hbar/HbarPlugin';
5
- export * from './hbar';
5
+ export * from './hbar';
6
+ export { WebBrowserPlugin } from './web-browser/WebBrowserPlugin';
@@ -12,6 +12,7 @@ import {
12
12
  InscribeHashinalTool,
13
13
  RetrieveInscriptionTool,
14
14
  } from '@hashgraphonline/standards-agent-kit';
15
+ import { fieldGuidanceRegistry, type FieldGuidance } from '../../forms/field-guidance-registry';
15
16
 
16
17
  /**
17
18
  * Plugin providing content inscription tools for Hedera
@@ -25,7 +26,8 @@ export class InscribePlugin extends BasePlugin {
25
26
  author = 'Hashgraph Online';
26
27
  namespace = 'inscribe';
27
28
 
28
- private tools: HederaTool[] = [];
29
+ private tools: any[] = [];
30
+ private providerId: string | null = null;
29
31
 
30
32
  override async initialize(context: GenericPluginContext): Promise<void> {
31
33
  await super.initialize(context);
@@ -41,6 +43,42 @@ export class InscribePlugin extends BasePlugin {
41
43
  try {
42
44
  this.initializeTools();
43
45
 
46
+ try {
47
+ const provider = {
48
+ getFieldGuidance: (fieldName: string): FieldGuidance | null => {
49
+ if (fieldName === 'name') {
50
+ return {
51
+ suggestions: [
52
+ 'Sunset Landscape #42',
53
+ 'Digital Abstract Art',
54
+ ],
55
+ contextualHelpText:
56
+ 'Create a distinctive name that collectors will find appealing',
57
+ };
58
+ }
59
+ if (fieldName === 'description') {
60
+ return {
61
+ fieldTypeOverride: 'textarea',
62
+ suggestions: ['A beautiful piece representing...'],
63
+ };
64
+ }
65
+ return null;
66
+ },
67
+ getGlobalGuidance: () => ({
68
+ qualityStandards: [
69
+ 'Use meaningful names that describe the artwork or content',
70
+ ],
71
+ }),
72
+ };
73
+ this.providerId = fieldGuidanceRegistry.registerToolProvider(
74
+ /hashinal/i,
75
+ provider,
76
+ { id: 'inscribe:hashinal:provider', priority: 1 }
77
+ );
78
+ } catch (e) {
79
+ this.context.logger.warn('Could not register Inscribe field guidance provider');
80
+ }
81
+
44
82
  this.context.logger.info(
45
83
  'Inscribe Plugin initialized successfully'
46
84
  );
@@ -95,8 +133,14 @@ export class InscribePlugin extends BasePlugin {
95
133
 
96
134
  override async cleanup(): Promise<void> {
97
135
  this.tools = [];
136
+ if (this.providerId) {
137
+ try {
138
+ fieldGuidanceRegistry.unregisterProvider(this.providerId);
139
+ } catch {}
140
+ this.providerId = null;
141
+ }
98
142
  if (this.context?.logger) {
99
143
  this.context.logger.info('Inscribe Plugin cleaned up');
100
144
  }
101
145
  }
102
- }
146
+ }
@@ -0,0 +1,128 @@
1
+ import {
2
+ BasePlugin,
3
+ type GenericPluginContext,
4
+ BaseHederaQueryTool,
5
+ type HederaAgentKit,
6
+ type HederaTool,
7
+ } from 'hedera-agent-kit';
8
+ import { z } from 'zod';
9
+
10
+ const PageSnapshotSchema = z.object({
11
+ url: z.string().url(),
12
+ maxCharacters: z
13
+ .number()
14
+ .int()
15
+ .min(256, 'Minimum length is 256 characters')
16
+ .max(8000, 'Maximum length is 8000 characters')
17
+ .optional()
18
+ .default(3000),
19
+ });
20
+
21
+ class WebPageSnapshotTool extends BaseHederaQueryTool<typeof PageSnapshotSchema> {
22
+ name = 'web_page_snapshot';
23
+ description = 'Fetches the visible text content of a web page for analysis.';
24
+ namespace = 'browser';
25
+ specificInputSchema = PageSnapshotSchema;
26
+
27
+ constructor(params: {
28
+ hederaKit: HederaAgentKit;
29
+ logger?: GenericPluginContext['logger'];
30
+ fetchImpl?: typeof fetch;
31
+ }) {
32
+ const { fetchImpl, ...rest } = params;
33
+ super(rest);
34
+ this.fetchImpl = fetchImpl ?? fetch;
35
+ }
36
+
37
+ private readonly fetchImpl: typeof fetch;
38
+
39
+ protected async executeQuery(
40
+ input: z.infer<typeof PageSnapshotSchema>
41
+ ): Promise<string> {
42
+ const maxChars = input.maxCharacters ?? 3000;
43
+
44
+ try {
45
+ const response = await this.fetchImpl(input.url, {
46
+ redirect: 'follow',
47
+ });
48
+
49
+ if (!response.ok) {
50
+ return `Failed to load ${input.url}: HTTP ${response.status}`;
51
+ }
52
+
53
+ const html = await response.text();
54
+ const text = this.normalizeHtml(html);
55
+
56
+ if (!text) {
57
+ return 'The fetched page did not contain readable text.';
58
+ }
59
+
60
+ return text.length > maxChars ? `${text.slice(0, maxChars)}…` : text;
61
+ } catch (error) {
62
+ this.logger.error('WebPageSnapshotTool failed', error);
63
+ return `Failed to fetch content for ${input.url}: ${
64
+ error instanceof Error ? error.message : String(error)
65
+ }`;
66
+ }
67
+ }
68
+
69
+ private normalizeHtml(html: string): string {
70
+ const withoutScripts = html
71
+ .replace(/<script[\s\S]*?<\/script>/gi, ' ')
72
+ .replace(/<style[\s\S]*?<\/style>/gi, ' ')
73
+ .replace(/<!--([\s\S]*?)-->/g, ' ');
74
+
75
+ const stripped = withoutScripts.replace(/<[^>]+>/g, ' ');
76
+ const decoded = stripped
77
+ .replace(/&nbsp;/gi, ' ')
78
+ .replace(/&amp;/gi, '&')
79
+ .replace(/&lt;/gi, '<')
80
+ .replace(/&gt;/gi, '>')
81
+ .replace(/&quot;/gi, '"')
82
+ .replace(/&#39;/gi, "'");
83
+
84
+ return decoded.replace(/\s+/g, ' ').trim();
85
+ }
86
+ }
87
+
88
+ export class WebBrowserPlugin extends BasePlugin<GenericPluginContext> {
89
+ id = 'web-browser';
90
+ name = 'Web Browser Plugin';
91
+ description =
92
+ 'Provides tools for fetching live web page content to enrich assistant understanding.';
93
+ version = '0.1.0';
94
+ author = 'Hashgraph Online';
95
+ namespace = 'browser';
96
+
97
+ private tools: HederaTool[] = [];
98
+
99
+ override async initialize(context: GenericPluginContext): Promise<void> {
100
+ await super.initialize(context);
101
+
102
+ const hederaKit = context.config.hederaKit as HederaAgentKit | undefined;
103
+
104
+ if (!hederaKit) {
105
+ this.context.logger.warn(
106
+ 'WebBrowserPlugin skipped because HederaAgentKit was not present in plugin context.'
107
+ );
108
+ this.tools = [];
109
+ return;
110
+ }
111
+
112
+ const tool = new WebPageSnapshotTool({
113
+ hederaKit,
114
+ logger: this.context.logger,
115
+ });
116
+
117
+ this.tools = [tool];
118
+ this.context.logger.info('Web Browser Plugin initialized with snapshot tool');
119
+ }
120
+
121
+ override getTools(): HederaTool[] {
122
+ return this.tools;
123
+ }
124
+
125
+ override async cleanup(): Promise<void> {
126
+ this.tools = [];
127
+ }
128
+ }
@@ -0,0 +1,46 @@
1
+ export type WalletNetwork = 'mainnet' | 'testnet';
2
+
3
+ export interface WalletStatus {
4
+ connected: boolean;
5
+ accountId?: string;
6
+ network?: WalletNetwork;
7
+ }
8
+
9
+ export interface WalletExecutorResult {
10
+ transactionId: string;
11
+ }
12
+
13
+ export interface StartInscriptionResult {
14
+ transactionBytes: string;
15
+ tx_id?: string;
16
+ topic_id?: string;
17
+ status?: string;
18
+ completed?: boolean;
19
+ }
20
+
21
+ export interface WalletBridgeProvider {
22
+ status: () => Promise<WalletStatus> | WalletStatus;
23
+ executeBytes: (
24
+ base64: string,
25
+ network: WalletNetwork
26
+ ) => Promise<WalletExecutorResult>;
27
+ startInscription?: (
28
+ request: Record<string, unknown>,
29
+ network: WalletNetwork
30
+ ) => Promise<StartInscriptionResult>;
31
+ startHCS?: (
32
+ op: string,
33
+ request: Record<string, unknown>,
34
+ network: WalletNetwork
35
+ ) => Promise<{ transactionBytes: string }>;
36
+ }
37
+
38
+ let providerRef: WalletBridgeProvider | null = null;
39
+
40
+ export function setWalletBridgeProvider(provider: WalletBridgeProvider): void {
41
+ providerRef = provider;
42
+ }
43
+
44
+ export function getWalletBridgeProvider(): WalletBridgeProvider | null {
45
+ return providerRef;
46
+ }