@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
@@ -1,4 +1,5 @@
1
1
  import type { FormFieldType, FieldOption } from './types';
2
+ import { Logger } from '@hashgraphonline/standards-sdk';
2
3
 
3
4
  /**
4
5
  * Field guidance configuration for providing contextual help and suggestions
@@ -90,6 +91,19 @@ export interface ToolFieldConfiguration {
90
91
  */
91
92
  class FieldGuidanceRegistry {
92
93
  private configurations: ToolFieldConfiguration[] = [];
94
+ private providers: Array<{
95
+ id: string;
96
+ priority: number;
97
+ pattern: string | RegExp;
98
+ provider: FieldGuidanceProvider;
99
+ order: number;
100
+ }> = [];
101
+ private registerOrderCounter = 0;
102
+ private logger: Logger;
103
+
104
+ constructor() {
105
+ this.logger = new Logger({ module: 'FieldGuidanceRegistry' });
106
+ }
93
107
 
94
108
  /**
95
109
  * Register field guidance for a specific tool
@@ -98,10 +112,55 @@ class FieldGuidanceRegistry {
98
112
  this.configurations.push(config);
99
113
  }
100
114
 
115
+ /**
116
+ * Register a provider for dynamic field/global guidance
117
+ */
118
+ registerToolProvider(
119
+ toolPattern: string | RegExp,
120
+ provider: FieldGuidanceProvider,
121
+ options?: { id?: string; priority?: number }
122
+ ): string {
123
+ const id = options?.id ?? `provider-${this.providers.length + 1}`;
124
+ const priority = options?.priority ?? 0;
125
+ if (this.providers.some((p) => p.id === id)) {
126
+ this.logger.error('Duplicate provider id', { id });
127
+ throw new Error('DUPLICATE_PROVIDER_ID');
128
+ }
129
+ this.providers.push({
130
+ id,
131
+ priority,
132
+ pattern: toolPattern,
133
+ provider,
134
+ order: this.registerOrderCounter++,
135
+ });
136
+ return id;
137
+ }
138
+
139
+ /** Unregister a provider by id */
140
+ unregisterProvider(id: string): void {
141
+ this.providers = this.providers.filter((p) => p.id !== id);
142
+ }
143
+
144
+ /** List registered providers */
145
+ listProviders(): Array<{
146
+ id: string;
147
+ priority: number;
148
+ pattern: string | RegExp;
149
+ }> {
150
+ return this.providers.map(({ id, priority, pattern }) => ({
151
+ id,
152
+ priority,
153
+ pattern,
154
+ }));
155
+ }
156
+
101
157
  /**
102
158
  * Get field guidance for a specific tool and field
103
159
  */
104
160
  getFieldGuidance(toolName: string, fieldName: string): FieldGuidance | null {
161
+ if (process.env.CA_FORM_GUIDANCE_ENABLED === 'false') {
162
+ return null;
163
+ }
105
164
  for (const config of this.configurations) {
106
165
  const matches =
107
166
  typeof config.toolPattern === 'string'
@@ -109,8 +168,31 @@ class FieldGuidanceRegistry {
109
168
  : config.toolPattern.test(toolName);
110
169
 
111
170
  if (matches && config.fields[fieldName]) {
112
- return config.fields[fieldName];
171
+ const staticGuidance = config.fields[fieldName];
172
+ const providers = this.pickMatchingProviders(toolName);
173
+ if (providers.length === 0) return staticGuidance;
174
+ let merged: FieldGuidance = { ...staticGuidance };
175
+ for (const p of [...providers].reverse()) {
176
+ const fromProvider = this.safeGetFieldGuidance(
177
+ p,
178
+ fieldName,
179
+ toolName
180
+ );
181
+ if (fromProvider) {
182
+ merged = this.mergeGuidance(merged, fromProvider);
183
+ }
184
+ }
185
+ return merged;
186
+ }
187
+ }
188
+ const providers = this.pickMatchingProviders(toolName);
189
+ if (providers.length > 0) {
190
+ let merged: FieldGuidance = {};
191
+ for (const p of [...providers].reverse()) {
192
+ const g = this.safeGetFieldGuidance(p, fieldName, toolName);
193
+ if (g) merged = this.mergeGuidance(merged, g);
113
194
  }
195
+ return Object.keys(merged).length > 0 ? merged : null;
114
196
  }
115
197
  return null;
116
198
  }
@@ -121,6 +203,9 @@ class FieldGuidanceRegistry {
121
203
  getGlobalGuidance(
122
204
  toolName: string
123
205
  ): ToolFieldConfiguration['globalGuidance'] | null {
206
+ if (process.env.CA_FORM_GUIDANCE_ENABLED === 'false') {
207
+ return null;
208
+ }
124
209
  for (const config of this.configurations) {
125
210
  const matches =
126
211
  typeof config.toolPattern === 'string'
@@ -128,9 +213,42 @@ class FieldGuidanceRegistry {
128
213
  : config.toolPattern.test(toolName);
129
214
 
130
215
  if (matches && config.globalGuidance) {
131
- return config.globalGuidance;
216
+ const base = config.globalGuidance;
217
+ const providers = this.pickMatchingProviders(toolName);
218
+ if (providers.length === 0) return base;
219
+ let mergedWarnings: string[] | undefined = base.warnings;
220
+ let mergedQuality: string[] | undefined = base.qualityStandards;
221
+ for (const p of [...providers].reverse()) {
222
+ const fromProvider = this.safeGetGlobalGuidance(p, toolName);
223
+ if (fromProvider) {
224
+ mergedWarnings = fromProvider.warnings ?? mergedWarnings;
225
+ mergedQuality = fromProvider.qualityStandards ?? mergedQuality;
226
+ }
227
+ }
228
+ const result: NonNullable<ToolFieldConfiguration['globalGuidance']> =
229
+ {};
230
+ if (mergedWarnings !== undefined) result.warnings = mergedWarnings;
231
+ if (mergedQuality !== undefined)
232
+ result.qualityStandards = mergedQuality;
233
+ return result;
132
234
  }
133
235
  }
236
+ const providers = this.pickMatchingProviders(toolName);
237
+ if (providers.length > 0) {
238
+ let mergedWarnings: string[] | undefined;
239
+ let mergedQuality: string[] | undefined;
240
+ for (const p of [...providers].reverse()) {
241
+ const g = this.safeGetGlobalGuidance(p, toolName);
242
+ if (g) {
243
+ mergedWarnings = g.warnings ?? mergedWarnings;
244
+ mergedQuality = g.qualityStandards ?? mergedQuality;
245
+ }
246
+ }
247
+ const result: NonNullable<ToolFieldConfiguration['globalGuidance']> = {};
248
+ if (mergedWarnings !== undefined) result.warnings = mergedWarnings;
249
+ if (mergedQuality !== undefined) result.qualityStandards = mergedQuality;
250
+ return Object.keys(result).length > 0 ? result : null;
251
+ }
134
252
  return null;
135
253
  }
136
254
 
@@ -222,194 +340,101 @@ class FieldGuidanceRegistry {
222
340
  */
223
341
  clear(): void {
224
342
  this.configurations = [];
343
+ this.providers = [];
344
+ this.registerOrderCounter = 0;
345
+ }
346
+
347
+ /** Choose matching provider by priority then last-in wins */
348
+ private pickMatchingProviders(toolName: string): Array<{
349
+ id: string;
350
+ provider: FieldGuidanceProvider;
351
+ priority: number;
352
+ order: number;
353
+ }> {
354
+ const matches = this.providers.filter((p) =>
355
+ typeof p.pattern === 'string'
356
+ ? toolName.toLowerCase().includes((p.pattern as string).toLowerCase())
357
+ : (p.pattern as RegExp).test(toolName)
358
+ );
359
+ const sorted = matches.sort((a, b) => {
360
+ if (b.priority !== a.priority) return b.priority - a.priority;
361
+ return b.order - a.order; // last-in wins when equal priority
362
+ });
363
+ return sorted.map((m) => ({
364
+ id: m.id,
365
+ provider: m.provider,
366
+ priority: m.priority,
367
+ order: m.order,
368
+ }));
369
+ }
370
+
371
+ private safeGetFieldGuidance(
372
+ winner: { id: string; provider: FieldGuidanceProvider },
373
+ fieldName: string,
374
+ toolName: string
375
+ ): FieldGuidance | null {
376
+ try {
377
+ return winner.provider.getFieldGuidance(fieldName, { toolName }) ?? null;
378
+ } catch (err) {
379
+ this.logger.warn('Provider getFieldGuidance failed', {
380
+ id: winner.id,
381
+ err,
382
+ });
383
+ return null;
384
+ }
385
+ }
386
+
387
+ private safeGetGlobalGuidance(
388
+ winner: { id: string; provider: FieldGuidanceProvider },
389
+ toolName: string
390
+ ): ToolFieldConfiguration['globalGuidance'] | null {
391
+ try {
392
+ return winner.provider.getGlobalGuidance?.(toolName) ?? null;
393
+ } catch (err) {
394
+ this.logger.warn('Provider getGlobalGuidance failed', {
395
+ id: winner.id,
396
+ err,
397
+ });
398
+ return null;
399
+ }
400
+ }
401
+
402
+ private mergeGuidance(
403
+ base: FieldGuidance,
404
+ over: FieldGuidance
405
+ ): FieldGuidance {
406
+ const out: FieldGuidance = {};
407
+ const suggestions = over.suggestions ?? base.suggestions;
408
+ if (suggestions !== undefined) out.suggestions = suggestions;
409
+ const predefinedOptions = over.predefinedOptions ?? base.predefinedOptions;
410
+ if (predefinedOptions !== undefined)
411
+ out.predefinedOptions = predefinedOptions;
412
+ const warnings = over.warnings ?? base.warnings;
413
+ if (warnings !== undefined) out.warnings = warnings;
414
+ const validationRules = over.validationRules ?? base.validationRules;
415
+ if (validationRules !== undefined) out.validationRules = validationRules;
416
+ const fieldTypeOverride = over.fieldTypeOverride ?? base.fieldTypeOverride;
417
+ if (fieldTypeOverride !== undefined)
418
+ out.fieldTypeOverride = fieldTypeOverride;
419
+ const contextualHelpText =
420
+ over.contextualHelpText ?? base.contextualHelpText;
421
+ if (contextualHelpText !== undefined)
422
+ out.contextualHelpText = contextualHelpText;
423
+ return out;
225
424
  }
226
425
  }
227
426
 
228
427
  export const fieldGuidanceRegistry = new FieldGuidanceRegistry();
229
428
 
230
- fieldGuidanceRegistry.registerToolConfiguration({
231
- toolPattern: /inscribe.*hashinal/i,
232
- globalGuidance: {
233
- warnings: [
234
- 'Avoid auto-generating technical metadata like file types or upload sources',
235
- 'Focus on collectible traits that add value to the NFT',
236
- ],
237
- qualityStandards: [
238
- 'Use meaningful names that describe the artwork or content',
239
- 'Include collectible attributes like rarity, style, or theme',
240
- 'Provide descriptions that tell a story or explain the concept',
241
- ],
242
- },
243
- fields: {
244
- name: {
245
- suggestions: [
246
- 'Sunset Landscape #42',
247
- 'Digital Abstract Art',
248
- 'Cosmic Dream Series',
249
- 'Portrait Study #5',
250
- ],
251
- validationRules: {
252
- rejectPatterns: [
253
- {
254
- pattern: /^untitled$/i,
255
- reason: 'Generic names like "Untitled" are not valuable for NFTs',
256
- },
257
- {
258
- pattern: /^image|file|upload/i,
259
- reason: 'Avoid technical file references in NFT names',
260
- },
261
- ],
262
- qualityChecks: {
263
- minNonTechnicalWords: 2,
264
- forbidTechnicalTerms: [
265
- 'MIME',
266
- 'upload',
267
- 'file type',
268
- 'buffer',
269
- 'source',
270
- ],
271
- },
272
- },
273
- contextualHelpText:
274
- 'Create a distinctive name that collectors will find appealing and memorable',
275
- },
276
-
277
- description: {
278
- suggestions: [
279
- 'A vibrant sunset captured in digital brushstrokes...',
280
- 'Part of the Cosmic Dreams collection, exploring...',
281
- 'This piece represents the intersection of technology and nature...',
282
- ],
283
- validationRules: {
284
- rejectPatterns: [
285
- {
286
- pattern: /uploaded by|file size|mime type|created from/i,
287
- reason: 'Avoid technical descriptions in NFT metadata',
288
- },
289
- ],
290
- qualityChecks: {
291
- minNonTechnicalWords: 8,
292
- forbidTechnicalTerms: [
293
- 'uploaded',
294
- 'file size',
295
- 'mime type',
296
- 'user upload',
297
- 'image format',
298
- 'pixel dimensions',
299
- 'file extension',
300
- ],
301
- requireSpecificTerms: [
302
- 'art',
303
- 'collection',
304
- 'piece',
305
- 'concept',
306
- 'inspired',
307
- 'represents',
308
- ],
309
- },
310
- },
311
- fieldTypeOverride: 'textarea',
312
- contextualHelpText:
313
- 'Describe the story, inspiration, or artistic vision behind this NFT',
314
- },
315
-
316
- creator: {
317
- suggestions: [
318
- '0.0.123456 (Hedera Account ID)',
319
- 'ArtistName',
320
- 'StudioBrand',
321
- 'CollectiveDAO',
322
- ],
323
- contextualHelpText:
324
- "Provide the creator's account ID, artist name, or brand identity",
325
- },
326
-
327
- attributes: {
328
- predefinedOptions: [
329
- {
330
- value: 'Rarity',
331
- label: 'Rarity',
332
- description: 'Common, Rare, Epic, Legendary',
333
- },
334
- {
335
- value: 'Color',
336
- label: 'Color',
337
- description: 'Primary colors or palette',
338
- },
339
- {
340
- value: 'Style',
341
- label: 'Style',
342
- description: 'Abstract, Realistic, Minimalist, etc.',
343
- },
344
- {
345
- value: 'Theme',
346
- label: 'Theme',
347
- description: 'Nature, Technology, Fantasy, etc.',
348
- },
349
- {
350
- value: 'Series',
351
- label: 'Series',
352
- description: 'Collection or series number',
353
- },
354
- {
355
- value: 'Element',
356
- label: 'Element',
357
- description: 'Fire, Water, Earth, Air, etc.',
358
- },
359
- {
360
- value: 'Power Level',
361
- label: 'Power Level',
362
- description: 'Numeric strength value',
363
- },
364
- {
365
- value: 'Edition',
366
- label: 'Edition',
367
- description: 'Special, Limited, First, etc.',
368
- },
369
- ],
370
- warnings: [
371
- {
372
- pattern: /mime.?type|file.?type|upload.?source/i,
373
- message: 'Technical metadata is not valuable for NFT collectors',
374
- },
375
- ],
376
- validationRules: {
377
- rejectPatterns: [
378
- {
379
- pattern: /^(mime.?type|file.?type|source|origin|upload)$/i,
380
- reason: 'Technical attributes are not collectible traits',
381
- },
382
- ],
383
- qualityChecks: {
384
- forbidTechnicalTerms: [
385
- 'MIME Type',
386
- 'File Type',
387
- 'Source',
388
- 'Origin',
389
- 'Upload Source',
390
- 'File Extension',
391
- 'Format',
392
- ],
393
- },
394
- },
395
- contextualHelpText:
396
- 'Add traits that make this NFT unique and valuable to collectors',
397
- },
398
-
399
- type: {
400
- predefinedOptions: [
401
- { value: 'Digital Art', label: 'Digital Art' },
402
- { value: 'Photography', label: 'Photography' },
403
- { value: 'Collectible Card', label: 'Collectible Card' },
404
- { value: 'Avatar', label: 'Avatar' },
405
- { value: 'Music', label: 'Music' },
406
- { value: 'Video', label: 'Video' },
407
- { value: '3D Model', label: '3D Model' },
408
- { value: 'Generative Art', label: 'Generative Art' },
409
- { value: 'Pixel Art', label: 'Pixel Art' },
410
- ],
411
- contextualHelpText:
412
- 'Choose the category that best represents your NFT content',
413
- },
414
- },
415
- });
429
+ /**
430
+ * Provider interface (optional, for dynamic guidance)
431
+ */
432
+ export interface FieldGuidanceProvider {
433
+ getFieldGuidance(
434
+ fieldName: string,
435
+ ctx: { toolName: string }
436
+ ): FieldGuidance | null;
437
+ getGlobalGuidance?(
438
+ toolName: string
439
+ ): ToolFieldConfiguration['globalGuidance'] | null;
440
+ }
@@ -187,11 +187,17 @@ export class FormGenerator {
187
187
  );
188
188
 
189
189
  const globalGuidance = fieldGuidanceRegistry.getGlobalGuidance(toolName);
190
- let description = this.generateFormDescription(toolName, missingFields.size);
191
-
190
+ let description = this.generateFormDescription(
191
+ toolName,
192
+ missingFields.size
193
+ );
194
+
192
195
  if (globalGuidance?.qualityStandards) {
193
- description += '\n\nQuality Guidelines:\n' +
194
- globalGuidance.qualityStandards.map(standard => `• ${standard}`).join('\n');
196
+ description +=
197
+ '\n\nQuality Guidelines:\n' +
198
+ globalGuidance.qualityStandards
199
+ .map((standard) => `• ${standard}`)
200
+ .join('\n');
195
201
  }
196
202
 
197
203
  return {
@@ -203,7 +209,7 @@ export class FormGenerator {
203
209
  metadata: {
204
210
  toolName,
205
211
  missingFieldCount: missingFields.size,
206
- globalGuidance
212
+ globalGuidance,
207
213
  },
208
214
  };
209
215
  }
@@ -453,8 +459,10 @@ export class FormGenerator {
453
459
  ): FormField {
454
460
  const type = this.mapFieldType(renderConfig?.fieldType, schema, fieldPath);
455
461
  const isRequired = this.isFieldRequired(schema, fieldPath || fieldName);
456
-
457
- const guidance = toolName ? fieldGuidanceRegistry.getFieldGuidance(toolName, fieldName) : null;
462
+
463
+ const guidance = toolName
464
+ ? fieldGuidanceRegistry.getFieldGuidance(toolName, fieldName)
465
+ : null;
458
466
  const finalType = guidance?.fieldTypeOverride || type;
459
467
 
460
468
  const field: FormField = {
@@ -474,7 +482,10 @@ export class FormGenerator {
474
482
  }
475
483
 
476
484
  if (guidance.predefinedOptions) {
477
- field.options = [...(field.options || []), ...guidance.predefinedOptions];
485
+ field.options = [
486
+ ...(field.options || []),
487
+ ...guidance.predefinedOptions,
488
+ ];
478
489
  }
479
490
 
480
491
  if (guidance.contextualHelpText) {
@@ -482,7 +493,7 @@ export class FormGenerator {
482
493
  }
483
494
 
484
495
  if (guidance.warnings) {
485
- field.warnings = guidance.warnings.map(w => w.message);
496
+ field.warnings = guidance.warnings.map((w) => w.message);
486
497
  }
487
498
 
488
499
  if (guidance.validationRules) {
@@ -491,7 +502,7 @@ export class FormGenerator {
491
502
  field.contextualGuidance = {
492
503
  qualityStandards: [],
493
504
  examples: guidance.suggestions || [],
494
- avoidPatterns: qualityChecks.forbidTechnicalTerms || []
505
+ avoidPatterns: qualityChecks.forbidTechnicalTerms || [],
495
506
  };
496
507
 
497
508
  if (qualityChecks.minNonTechnicalWords) {
@@ -502,7 +513,9 @@ export class FormGenerator {
502
513
 
503
514
  if (qualityChecks.forbidTechnicalTerms) {
504
515
  field.contextualGuidance.qualityStandards?.push(
505
- `Avoid technical terms like: ${qualityChecks.forbidTechnicalTerms.join(', ')}`
516
+ `Avoid technical terms like: ${qualityChecks.forbidTechnicalTerms.join(
517
+ ', '
518
+ )}`
506
519
  );
507
520
  }
508
521
  }
@@ -817,7 +830,10 @@ export class FormGenerator {
817
830
  zodSchema: z.ZodObject<z.ZodRawShape>,
818
831
  partialInput?: Record<string, unknown>,
819
832
  missingFields?: Set<string>
820
- ): { jsonSchema: Record<string, unknown>; uiSchema: Record<string, unknown> } {
833
+ ): {
834
+ jsonSchema: Record<string, unknown>;
835
+ uiSchema: Record<string, unknown>;
836
+ } {
821
837
  const fullJsonSchema = zodToJsonSchema(zodSchema, {
822
838
  target: 'jsonSchema7',
823
839
  });
package/src/index.ts CHANGED
@@ -26,3 +26,4 @@ export * from './services';
26
26
  export * from './langchain';
27
27
  export * from './tools';
28
28
  export * from './utils';
29
+ export * from './runtime/wallet-bridge';
@@ -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
+ }