UNPKG

@hashgraphonline/conversational-agent

Version:

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

1 lines 190 kB
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("hedera-agent-kit"),t=require("@hashgraphonline/standards-agent-kit"),r=require("@hashgraphonline/standards-sdk"),o=require("zod"),s=require("@hashgraph/sdk"),n=require("bignumber.js"),i=require("@langchain/core/tools"),a=require("@ethersphere/bee-js"),c=require("fs"),l=require("path"),g=require("util"),h=require("@ethereumjs/wallet"),u=require("crypto"),d=require("langchain/agents"),m=require("zod-to-json-schema"),p=require("@langchain/core/prompts"),f=require("@langchain/openai"),y=require("@modelcontextprotocol/sdk/client/index.js"),w=require("@modelcontextprotocol/sdk/client/stdio.js"),b=require("@langchain/core/messages"),T=require("tiktoken"),S=require("@langchain/anthropic");class v extends e.BasePlugin{constructor(){super(...arguments),this.id="hcs-10",this.name="HCS-10 Plugin",this.description="HCS-10 agent tools for decentralized agent registration, connections, and messaging on Hedera",this.version="1.0.0",this.author="Hashgraph Online",this.namespace="hcs10",this.tools=[]}async initialize(e){await super.initialize(e);const o=e.config.hederaKit;var s;if(o)try{this.stateManager=e.stateManager||e.config.stateManager||this.appConfig?.stateManager||new t.OpenConvaiState;const a=o.signer.getAccountId().toString(),c="returnBytes"===String(o.operationalMode||"returnBytes");let l,g="",h="",u=o.signer.getOperatorPrivateKey();try{l="function"==typeof u?.toString?u.toString():"";const e=new r.HCS10Client({network:o.network,operatorId:a,operatorPrivateKey:u,logLevel:"error"}),t=await e.retrieveProfile(a);t.success&&t.topicInfo&&(g=t.topicInfo.inboundTopic,h=t.topicInfo.outboundTopic)}catch(n){this.context.logger.warn("Skipping profile topic discovery",n)}const d={name:`Agent ${a}`,accountId:a,inboundTopicId:g,outboundTopicId:h};if(!c&&l&&(d.privateKey=l),this.stateManager.setCurrentAgent(d),this.context.logger.info(`Set current agent: ${a} with topics ${g}/${h}`),!c&&this.stateManager&&!this.stateManager.getConnectionsManager())try{const e=new r.HCS10Client({network:o.network,operatorId:a,operatorPrivateKey:u??"",logLevel:"error"});"object"==typeof(s=this.stateManager)&&null!==s&&"initializeConnectionsManager"in s&&"function"==typeof s.initializeConnectionsManager?this.stateManager.initializeConnectionsManager(e):this.context.logger.warn("StateManager does not support connection manager initialization"),this.context.logger.info("ConnectionsManager initialized in HCS10Plugin")}catch(i){this.context.logger.warn("Could not initialize ConnectionsManager:",i)}this.initializeTools(),this.context.logger.info("HCS-10 Plugin initialized successfully")}catch(a){this.context.logger.error("Failed to initialize HCS-10 plugin:",a)}else this.context.logger.warn("HederaKit not found in context. HCS-10 tools will not be available.")}initializeTools(){if(!this.stateManager)throw new Error("StateManager must be initialized before creating tools");const e=this.context.config.hederaKit;if(!e)throw new Error("HederaKit not found in context config");const r=new t.HCS10Builder(e,this.stateManager);this.tools=[new t.RegisterAgentTool({hederaKit:e,hcs10Builder:r,logger:this.context.logger}),new t.FindRegistrationsTool({hederaKit:e,hcs10Builder:r,logger:this.context.logger}),new t.RetrieveProfileTool({hederaKit:e,hcs10Builder:r,logger:this.context.logger}),new t.InitiateConnectionTool({hederaKit:e,hcs10Builder:r,logger:this.context.logger}),new t.ListConnectionsTool({hederaKit:e,hcs10Builder:r,logger:this.context.logger}),new t.SendMessageToConnectionTool({hederaKit:e,hcs10Builder:r,logger:this.context.logger}),new t.CheckMessagesTool({hederaKit:e,hcs10Builder:r,logger:this.context.logger}),new t.ConnectionMonitorTool({hederaKit:e,hcs10Builder:r,logger:this.context.logger}),new t.ManageConnectionRequestsTool({hederaKit:e,hcs10Builder:r,logger:this.context.logger}),new t.AcceptConnectionRequestTool({hederaKit:e,hcs10Builder:r,logger:this.context.logger}),new t.ListUnapprovedConnectionRequestsTool({hederaKit:e,hcs10Builder:r,logger:this.context.logger})]}getTools(){return this.tools}getStateManager(){return this.stateManager}async cleanup(){this.tools=[],delete this.stateManager,this.context?.logger&&this.context.logger.info("HCS-10 Plugin cleaned up")}}class k extends e.BasePlugin{constructor(){super(...arguments),this.id="hcs-2",this.name="HCS-2 Plugin",this.description="HCS-2 registry management tools for decentralized registries on Hedera",this.version="1.0.0",this.author="Hashgraph Online",this.namespace="hcs2",this.tools=[]}async initialize(e){await super.initialize(e);if(e.config.hederaKit)try{this.initializeTools(),this.context.logger.info("HCS-2 Plugin initialized successfully")}catch(t){this.context.logger.error("Failed to initialize HCS-2 plugin:",t)}else this.context.logger.warn("HederaKit not found in context. HCS-2 tools will not be available.")}initializeTools(){const e=this.context.config.hederaKit;if(!e)throw new Error("HederaKit not found in context config");const r=new t.HCS2Builder(e);this.tools=[new t.CreateRegistryTool({hederaKit:e,hcs2Builder:r,logger:this.context.logger}),new t.RegisterEntryTool({hederaKit:e,hcs2Builder:r,logger:this.context.logger}),new t.UpdateEntryTool({hederaKit:e,hcs2Builder:r,logger:this.context.logger}),new t.DeleteEntryTool({hederaKit:e,hcs2Builder:r,logger:this.context.logger}),new t.MigrateRegistryTool({hederaKit:e,hcs2Builder:r,logger:this.context.logger}),new t.QueryRegistryTool({hederaKit:e,hcs2Builder:r,logger:this.context.logger})]}getTools(){return this.tools}async cleanup(){this.tools=[],this.context?.logger&&this.context.logger.info("HCS-2 Plugin cleaned up")}}const C=new class{constructor(){this.configurations=[],this.providers=[],this.registerOrderCounter=0,this.logger=new r.Logger({module:"FieldGuidanceRegistry"})}registerToolConfiguration(e){this.configurations.push(e)}registerToolProvider(e,t,r){const o=r?.id??`provider-${this.providers.length+1}`,s=r?.priority??0;if(this.providers.some(e=>e.id===o))throw this.logger.error("Duplicate provider id",{id:o}),new Error("DUPLICATE_PROVIDER_ID");return this.providers.push({id:o,priority:s,pattern:e,provider:t,order:this.registerOrderCounter++}),o}unregisterProvider(e){this.providers=this.providers.filter(t=>t.id!==e)}listProviders(){return this.providers.map(({id:e,priority:t,pattern:r})=>({id:e,priority:t,pattern:r}))}getFieldGuidance(e,t){if("false"===process.env.CA_FORM_GUIDANCE_ENABLED)return null;for(const o of this.configurations){if(("string"==typeof o.toolPattern?e.toLowerCase().includes(o.toolPattern.toLowerCase()):o.toolPattern.test(e))&&o.fields[t]){const r=o.fields[t],s=this.pickMatchingProviders(e);if(0===s.length)return r;let n={...r};for(const o of[...s].reverse()){const r=this.safeGetFieldGuidance(o,t,e);r&&(n=this.mergeGuidance(n,r))}return n}}const r=this.pickMatchingProviders(e);if(r.length>0){let o={};for(const s of[...r].reverse()){const r=this.safeGetFieldGuidance(s,t,e);r&&(o=this.mergeGuidance(o,r))}return Object.keys(o).length>0?o:null}return null}getGlobalGuidance(e){if("false"===process.env.CA_FORM_GUIDANCE_ENABLED)return null;for(const r of this.configurations){if(("string"==typeof r.toolPattern?e.toLowerCase().includes(r.toolPattern.toLowerCase()):r.toolPattern.test(e))&&r.globalGuidance){const t=r.globalGuidance,o=this.pickMatchingProviders(e);if(0===o.length)return t;let s=t.warnings,n=t.qualityStandards;for(const r of[...o].reverse()){const t=this.safeGetGlobalGuidance(r,e);t&&(s=t.warnings??s,n=t.qualityStandards??n)}const i={};return void 0!==s&&(i.warnings=s),void 0!==n&&(i.qualityStandards=n),i}}const t=this.pickMatchingProviders(e);if(t.length>0){let r,o;for(const n of[...t].reverse()){const t=this.safeGetGlobalGuidance(n,e);t&&(r=t.warnings??r,o=t.qualityStandards??o)}const s={};return void 0!==r&&(s.warnings=r),void 0!==o&&(s.qualityStandards=o),Object.keys(s).length>0?s:null}return null}validateFieldValue(e,t,r){const o=this.getFieldGuidance(e,t),s=[],n=[];if(!o||"string"!=typeof r)return{isValid:!0,warnings:s,errors:n};if(o.warnings)for(const i of o.warnings)i.pattern.test(r)&&s.push(i.message);if(o.validationRules){const{rejectPatterns:e,qualityChecks:t}=o.validationRules;if(e)for(const o of e)o.pattern.test(r)&&n.push(`Rejected: ${o.reason}`);if(t){if(t.forbidTechnicalTerms){const e=r.toLowerCase();for(const r of t.forbidTechnicalTerms)e.includes(r.toLowerCase())&&n.push(`Avoid technical terms like "${r}" in NFT metadata`)}if(t.requireSpecificTerms){const e=r.toLowerCase();t.requireSpecificTerms.some(t=>e.includes(t.toLowerCase()))||s.push(`Consider including terms like: ${t.requireSpecificTerms.join(", ")}`)}if(t.minNonTechnicalWords){r.split(/\s+/).filter(e=>e.length>2).length<t.minNonTechnicalWords&&s.push(`Consider providing more descriptive content (at least ${t.minNonTechnicalWords} meaningful words)`)}}}return{isValid:0===n.length,warnings:s,errors:n}}clear(){this.configurations=[],this.providers=[],this.registerOrderCounter=0}pickMatchingProviders(e){return this.providers.filter(t=>"string"==typeof t.pattern?e.toLowerCase().includes(t.pattern.toLowerCase()):t.pattern.test(e)).sort((e,t)=>t.priority!==e.priority?t.priority-e.priority:t.order-e.order).map(e=>({id:e.id,provider:e.provider,priority:e.priority,order:e.order}))}safeGetFieldGuidance(e,t,r){try{return e.provider.getFieldGuidance(t,{toolName:r})??null}catch(o){return this.logger.warn("Provider getFieldGuidance failed",{id:e.id,err:o}),null}}safeGetGlobalGuidance(e,t){try{return e.provider.getGlobalGuidance?.(t)??null}catch(r){return this.logger.warn("Provider getGlobalGuidance failed",{id:e.id,err:r}),null}}mergeGuidance(e,t){const r={},o=t.suggestions??e.suggestions;void 0!==o&&(r.suggestions=o);const s=t.predefinedOptions??e.predefinedOptions;void 0!==s&&(r.predefinedOptions=s);const n=t.warnings??e.warnings;void 0!==n&&(r.warnings=n);const i=t.validationRules??e.validationRules;void 0!==i&&(r.validationRules=i);const a=t.fieldTypeOverride??e.fieldTypeOverride;void 0!==a&&(r.fieldTypeOverride=a);const c=t.contextualHelpText??e.contextualHelpText;return void 0!==c&&(r.contextualHelpText=c),r}};class I extends e.BasePlugin{constructor(){super(...arguments),this.id="inscribe",this.name="Inscribe Plugin",this.description="Content inscription tools for storing data on Hedera Consensus Service",this.version="1.0.0",this.author="Hashgraph Online",this.namespace="inscribe",this.tools=[],this.providerId=null}async initialize(e){await super.initialize(e);if(e.config.hederaKit)try{this.initializeTools();try{const e={getFieldGuidance:e=>"name"===e?{suggestions:["Sunset Landscape #42","Digital Abstract Art"],contextualHelpText:"Create a distinctive name that collectors will find appealing"}:"description"===e?{fieldTypeOverride:"textarea",suggestions:["A beautiful piece representing..."]}:null,getGlobalGuidance:()=>({qualityStandards:["Use meaningful names that describe the artwork or content"]})};this.providerId=C.registerToolProvider(/hashinal/i,e,{id:"inscribe:hashinal:provider",priority:1})}catch(t){this.context.logger.warn("Could not register Inscribe field guidance provider")}this.context.logger.info("Inscribe Plugin initialized successfully")}catch(r){this.context.logger.error("Failed to initialize Inscribe plugin:",r)}else this.context.logger.warn("HederaKit not found in context. Inscription tools will not be available.")}initializeTools(){const e=this.context.config.hederaKit;if(!e)throw new Error("HederaKit not found in context config");const r=new t.InscriberBuilder(e);this.tools=[new t.InscribeFromUrlTool({hederaKit:e,inscriberBuilder:r,logger:this.context.logger}),new t.InscribeFromFileTool({hederaKit:e,inscriberBuilder:r,logger:this.context.logger}),new t.InscribeFromBufferTool({hederaKit:e,inscriberBuilder:r,logger:this.context.logger}),new t.InscribeHashinalTool({hederaKit:e,inscriberBuilder:r,logger:this.context.logger}),new t.RetrieveInscriptionTool({hederaKit:e,inscriberBuilder:r,logger:this.context.logger})]}getTools(){return this.tools}async cleanup(){if(this.tools=[],this.providerId){try{C.unregisterProvider(this.providerId)}catch{}this.providerId=null}this.context?.logger&&this.context.logger.info("Inscribe Plugin cleaned up")}}class x extends e.BaseServiceBuilder{constructor(e){super(e)}transferHbar(e,t=!0){this.clearNotes();const r=new s.TransferTransaction;if(!e.transfers||0===e.transfers.length)throw new Error("HbarTransferParams must include at least one transfer.");let o=new n(0),i=!1;if(t&&this.kit.userAccountId&&"provideBytes"===this.kit.operationalMode&&1===e.transfers.length){const t=e.transfers[0],o="string"==typeof t.amount||"number"==typeof t.amount?t.amount:t.amount.toString(),a=new n(o);if(a.isPositive()){const e="string"==typeof t.accountId?s.AccountId.fromString(t.accountId):t.accountId,o=a.toFixed(8,n.ROUND_DOWN),c=s.Hbar.fromString(o);this.logger.info(`[AccountBuilder.transferHbar] Configuring user-initiated scheduled transfer: ${c.toString()} from ${this.kit.userAccountId} to ${e.toString()}`),this.addNote(`Configured HBAR transfer from your account (${this.kit.userAccountId}) to ${e.toString()} for ${c.toString()}.`),r.addHbarTransfer(e,c),r.addHbarTransfer(s.AccountId.fromString(this.kit.userAccountId),c.negated()),i=!0}}if(!i){const t=[];for(const r of e.transfers){const e="string"==typeof r.accountId?s.AccountId.fromString(r.accountId):r.accountId,i="string"==typeof r.amount||"number"==typeof r.amount?r.amount:r.amount.toString(),a=new n(i),c=a.toFixed(8,n.ROUND_DOWN);this.logger.info(`Processing transfer: ${i} HBAR (rounded to ${c}) for account ${e.toString()}`);const l=s.Hbar.fromString(c);t.push({accountId:e,amount:a,hbar:l});const g=l.toTinybars();o=o.plus(g.toString())}if(!o.isZero()&&(this.logger.warn(`Transfer sum not zero: ${o.toString()} tinybars off. Adjusting last transfer.`),t.length>0)){const e=t[t.length-1],r=o.dividedBy(-1e8),i=e.amount.plus(r).toFixed(8,n.ROUND_DOWN);e.hbar=s.Hbar.fromString(i),this.logger.info(`Adjusted last transfer for ${e.accountId.toString()} to ${i} HBAR`)}for(const e of t)r.addHbarTransfer(e.accountId,e.hbar)}return void 0!==e.memo&&(null===e.memo?this.logger.warn("Received null for memo in transferHbar."):r.setTransactionMemo(e.memo)),this.setCurrentTransaction(r),this}}const M=o.z.object({accountId:o.z.string().describe('Account ID for the transfer (e.g., "0.0.xxxx").'),amount:o.z.union([o.z.number(),o.z.string()]).describe("HBAR amount in decimal format (e.g., 1 for 1 HBAR, 0.5 for 0.5 HBAR). Positive for credit, negative for debit. DO NOT multiply by 10^8 for tinybars - just use the HBAR amount directly.")}),E=o.z.object({transfers:o.z.array(M).min(1).describe('Array of transfers. For simple transfers from your operator account, just include the recipient with positive amount: [{accountId: "0.0.800", amount: 1}]. For complex multi-party transfers, include all parties with negative amounts for senders and positive for receivers.'),memo:o.z.string().optional().describe("Optional. Memo for the transaction.")});class A extends e.BaseHederaTransactionTool{constructor(){super(...arguments),this.name="hedera-account-transfer-hbar-v2",this.description='PRIMARY TOOL FOR HBAR TRANSFERS: Transfers HBAR between accounts. For simple transfers from the operator account, just specify the recipient with a positive amount (e.g., [{accountId: "0.0.800", amount: 1}] to send 1 HBAR to 0.0.800). The sender will be automatically added. For multi-party transfers (e.g., "A sends 5 HBAR to C and B sends 3 HBAR to C"), include ALL transfers with their amounts (negative for senders, positive for receivers).',this.specificInputSchema=E,this.namespace="account"}getServiceBuilder(){return new x(this.hederaKit)}async callBuilderMethod(e,t){await e.transferHbar(t)}}class F extends i.StructuredTool{constructor(e,t){super(),this.name="hedera-hts-airdrop-token",this.description="Airdrops fungible tokens to multiple recipients. Automatically converts human-readable amounts to smallest units based on token decimals.",this.schema=o.z.object({tokenId:o.z.string().describe('The ID of the fungible token to airdrop (e.g., "0.0.yyyy").'),recipients:o.z.array(o.z.object({accountId:o.z.string().describe('Recipient account ID (e.g., "0.0.xxxx").'),amount:o.z.union([o.z.number(),o.z.string()]).describe('Amount in human-readable format (e.g., "10" for 10 tokens).')})).min(1).describe("Array of recipient objects, each with accountId and amount."),memo:o.z.string().optional().describe("Optional. Memo for the transaction.")}),this.originalTool=e,this.agentKit=t,this.logger=new r.Logger({module:"AirdropToolWrapper"})}async _call(e){try{this.logger.info(`Processing airdrop request for token ${e.tokenId} with ${e.recipients.length} recipients`);const t=(await this.getTokenInfo(e.tokenId)).decimals||0;this.logger.info(`Token ${e.tokenId} has ${t} decimal places`);const r=e.recipients.map(e=>{const r="string"==typeof e.amount?parseFloat(e.amount):e.amount,o=this.convertToSmallestUnits(r,t);return this.logger.info(`Converting amount for ${e.accountId}: ${r} tokens → ${o} smallest units`),{...e,amount:o.toString()}}),o={...e,recipients:r};return this.logger.info("Calling original airdrop tool with converted amounts"),await this.originalTool._call(o)}catch(t){throw this.logger.error("Error in airdrop tool wrapper:",t),t}}convertToSmallestUnits(e,t){return Math.floor(e*Math.pow(10,t))}async getTokenInfo(e){try{return await this.queryTokenInfo(e)}catch(t){throw t}}async queryTokenInfo(e){try{this.logger.info("Querying token info using mirror node");const t=this.agentKit.mirrorNode;if(t){const r=await t.getTokenInfo(e);if(r&&void 0!==r.decimals){const t=parseInt(r.decimals.toString())||0;return this.logger.info(`Token ${e} found with ${t} decimals`),{...r,decimals:t}}}else{this.logger.info("MirrorNode not found in agentKit, attempting to access via fetch");const t="mainnet"===(this.agentKit.network||"testnet")?"https://mainnet.mirrornode.hedera.com":"https://testnet.mirrornode.hedera.com",r=await fetch(`${t}/api/v1/tokens/${e}`);if(r.ok){const t=await r.json(),o=parseInt(String(t.decimals||"0"));return this.logger.info(`Token ${e} found with ${o} decimals via API`),{...t,decimals:o}}}throw new Error("Token data not found or missing decimals field")}catch(t){return this.logger.warn(`Failed to query token info for ${e}:`,t),this.logger.info("Falling back to assumed 0 decimal places (smallest units)"),{decimals:0}}}}class R extends e.BasePlugin{constructor(){super(...arguments),this.id="hbar",this.name="HBAR Plugin",this.description="HBAR operations: transfer tool with robust decimal handling and compatibility with airdrop improvements",this.version="1.0.0",this.author="Hashgraph Online",this.namespace="account",this.tools=[],this.originalAirdropTool=null}async initialize(e){await super.initialize(e);if(e.config.hederaKit)try{this.initializeTools(),this.context.logger.info("HBAR Plugin initialized successfully")}catch(t){this.context.logger.error("Failed to initialize HBAR plugin:",t)}else this.context.logger.warn("HederaKit not found in context. HBAR tools will not be available.")}initializeTools(){const t=this.context.config.hederaKit;if(!t)throw new Error("HederaKit not found in context config");const r=new A({hederaKit:t,logger:this.context.logger});this.tools=[r];try{this.context.logger.info("Creating wrapper for passed original airdrop tool");const r=new e.HederaAirdropTokenTool({hederaKit:t,logger:this.context.logger}),o=new F(r,t);this.tools.push(o),this.context.logger.info("Added wrapped airdrop tool to HBAR Plugin")}catch(o){this.context.logger.error("Error creating airdrop tool wrapper:",o)}this.context.logger.info(`HBAR Plugin tools initialized with ${this.tools.length} tools`)}getTools(){return this.tools}async shutdown(){this.tools=[]}}const P=404,O=400,N="Endpoint not found. If using Swarm Gateway, postage stamp management endpoints are not available.",L="If using Swarm Gateway, tag endpoints are not available.";function $(e){const t=new Uint8Array(e.length/2);for(let r=0;r<e.length;r+=2)t[r/2]=parseInt(e.slice(r,r+2),16);return t}const B=e=>({stampID:"string"==typeof e.batchID?e.batchID:e.batchID.toHex(),usage:e.usageText,capacity:`${e.remainingSize.toFormattedString()} remaining out of ${e.size.toFormattedString()}`,immutable:e.immutableFlag,ttl:`${e.duration.represent()} (${e.duration.toEndDate().toDateString()})`}),z=e=>({content:[{type:"text",text:JSON.stringify(e,null,2)}],structuredContent:e}),D=(e,t)=>"object"==typeof e&&null!==e&&"status"in e&&e.status===t,H=e=>"object"==typeof e&&null!==e&&"responseBody"in e&&"object"==typeof e.responseBody&&null!==e.responseBody&&"message"in e.responseBody?e.responseBody.message:"",j=async(e,t,r)=>{let o=e;const s=r.autoAssignStamp??!0;let n=0;if(!o&&!s)throw new Error("No postageBatchId was provided. Please repeat the prompt and also specify the usable postage batch id.");if(!o)try{(await t.getPostageBatches()).forEach(e=>{if(!e.usable)return;const t=e.remainingSize.toBytes();t>n&&(n=t,o=e.batchID.toHex())})}catch(i){if(!D(i,P))throw new Error("Retrieval of postage batches failed.");o="0000000000000000000000000000000000000000000000000000000000000000"}if(!o)throw new Error("There is no usable postage batch with capacity.");return o},_={ms:1,milli:1,millis:1,millisecond:1,milliseconds:1,s:1e3,sec:1e3,second:1e3,seconds:1e3,m:6e4,min:6e4,minute:6e4,minutes:6e4,h:36e5,hour:36e5,hours:36e5,d:864e5,day:864e5,days:864e5,w:6048e5,week:6048e5,weeks:6048e5,month:2592e6,months:2592e6,y:31536e6,year:31536e6,years:31536e6};function U(e){const t=parseFloat(e);if(isNaN(t))throw Error("makeDate got NaN for input");const r=e.replace(/^-?[0-9.]+/,"").trim().toLowerCase(),o=_[r];if(!o)throw Error(`Unknown unit: "${r}"`);return t*o}const q=o.z.object({leastUsed:o.z.boolean().optional(),limit:o.z.number().optional(),minUsage:o.z.number().optional(),maxUsage:o.z.number().optional()});class K extends e.BaseHederaQueryTool{constructor(e){const{bee:t,config:r,...o}=e;super(o),this.name="swarm-list-postage-stamps",this.description="\n List the available postage stamps.\n leastUsed: A boolean value that tells if stamps are sorted so least used comes first.\n limit: Limit is the maximum number of returned stamps.\n minUsage: Only list stamps with at least this usage percentage.\n maxUsage: Only list stamps with at most this usage percentage. \n ",this.namespace="swarm",this.specificInputSchema=q,this.bee=t,this.config=r}async executeQuery(e){const{leastUsed:t,limit:r,minUsage:o,maxUsage:s}=e;let n;try{n=await this.bee.getPostageBatches()}catch(c){let e="Retrieval of postage batches failed.";throw D(c,P)&&(e=N),this.logger.error(e,c),new Error(e)}let i=n.map(e=>({...e,batchID:e.batchID.toHex()})).filter(e=>{if(!e.usable)return!1;const t=100*e.usage;return!(void 0!==o&&t<o)&&!(void 0!==s&&t>s)});Boolean(t)&&i.length&&(i=i.sort((e,t)=>e.usage-t.usage)),void 0!==r&&r<i.length&&(i=i.slice(0,r));const a=i.map(e=>B(e));return z({raw:i,summary:a})}}const G=o.z.object({data:o.z.string(),redundancyLevel:o.z.number().optional(),postageBatchId:o.z.string().optional()});class W extends e.BaseHederaQueryTool{constructor(e){const{bee:t,config:r,...o}=e;super(o),this.name="swarm-upload-data",this.description="\n Upload text data to Swarm.\n data: Arbitrary string to upload.\n redundancyLevel: Redundancy level for fault tolerance: 0 - none, 1 - medium, 2 - strong, 3 - insane, 4 - paranoid (higher values provide better fault tolerance but increase storage overhead). Optional, value is 0 if not requested.\n postageBatchId: The postage stamp batch ID which will be used to perform the upload, if it is provided.\n ",this.namespace="swarm",this.specificInputSchema=G,this.bee=t,this.config=r}async executeQuery(e){const{data:t,redundancyLevel:r,postageBatchId:o}=e;if(!t)throw this.logger.error("Missing required parameter: data."),new Error("Missing required parameter: data.");let s="";try{s=await j(o,this.bee,this.config)}catch(c){let e="Upload data failed.";throw c instanceof Error&&(e=c.message),this.logger.error(e),new Error(e)}const n=globalThis.Buffer.from(t),i=r?{redundancyLevel:r}:void 0;let a;try{a=await this.bee.uploadData(s,n,i)}catch(c){let e="Unable to upload data.";throw D(c,O)&&(e=H(c)),this.logger.error(e,c),new Error(e)}return z({reference:a.reference.toString(),url:this.bee.url+"/bytes/"+a.reference.toString(),message:"Data successfully uploaded to Swarm"})}}const J=o.z.object({reference:o.z.string()});class V extends e.BaseHederaQueryTool{constructor(e){const{bee:t,config:r,...o}=e;super(o),this.name="swarm-download-data",this.description="\n Downloads immutable data from a Swarm content address hash.\n reference: Swarm reference hash.\n ",this.namespace="swarm",this.specificInputSchema=J,this.bee=t,this.config=r}async executeQuery(e){const{reference:t}=e;if(!t)throw this.logger.error("Missing required parameter: reference."),new Error("Missing required parameter: reference.");if(64!==t.length&&66!==t.length)throw this.logger.error("Invalid Swarm content address hash value for reference."),new Error("Invalid Swarm content address hash value for reference.");let r;try{r=await this.bee.downloadData(t)}catch(s){let e="Downloading data failed.";throw D(s,O)&&(e=H(s)),this.logger.error(e,s),new Error(e)}const o=r.toUtf8();return z({textData:o})}}const Z=o.z.object({size:o.z.number(),duration:o.z.string(),label:o.z.string().optional()});class X extends e.BaseHederaQueryTool{constructor(e){const{bee:t,config:r,...o}=e;super(o),this.name="swarm-create-postage-stamp",this.description="\n Buy postage stamp based on size in megabytes and duration.\n size: The storage size in MB (Megabytes). These other size units convert like this to MB: 1 byte = 0.000001 MB, 1 KB = 0.001 MB, 1GB= 1000MB.\n duration: Duration for which the data should be stored. Time to live of the postage stamp, e.g. 1d - 1 day, 1w - 1 week, 1month - 1 month.\n label: Sets label for the postage batch (omit if the user didn't ask for one). Do not set a label with with specific capacity values because they can get misleading.\n ",this.namespace="swarm",this.specificInputSchema=Z,this.bee=t,this.config=r}async executeQuery(e){const{size:t,duration:r,label:o}=e;if(!t)throw this.logger.error("Missing required parameter: size."),new Error("Missing required parameter: size.");if(!r)throw this.logger.error("Missing required parameter: duration."),new Error("Missing required parameter: duration.");let s,n;try{s=U(r)}catch(i){throw this.logger.error("Invalid parameter: duration."),new Error("Invalid parameter: duration.")}try{let e={};void 0!==o&&(e={label:o});const r=this.bee.buyStorage(a.Size.fromMegabytes(t),a.Duration.fromMilliseconds(s),e),[i,c]=await(async(e,t)=>{let r=!1;const o=new Promise(e=>setTimeout(()=>{r=!0,e(!0)},t));return[await Promise.race([e,o]),r]})(r,3e4);if(c)return JSON.stringify({content:[{type:"text",text:"Purchase of postage batch is in progress, it may take a few minutes. Please list you batches after a few minutes to find it."}]});n=i}catch(c){let e="Unable to buy storage.";throw D(c,P)?e=N:D(c,O)&&(e=H(c)),this.logger.error(e,c),new Error(e)}return{content:[{type:"text",text:`Postage batch ID: ${n.toHex()}`}]}}}const Y=o.z.object({postageBatchId:o.z.string(),duration:o.z.string().optional(),size:o.z.number().optional()});class Q extends e.BaseHederaQueryTool{constructor(e){const{bee:t,config:r,...o}=e;super(o),this.name="swarm-extend-postage-stamp",this.description="Increase the duration (relative to current duration) or size (in megabytes) of a postage stamp.\n postageBatchId: The id of the batch for which extend is performed.\n size: The storage size in MB (Megabytes). These other size units convert like this to MB: 1 byte = 0.000001 MB, 1 KB = 0.001 MB, 1GB= 1000MB.\n duration: Duration for which the data should be stored. Time to live of the postage stamp, e.g. 1d - 1 day, 1w - 1 week, 1month - 1 month.\n ",this.namespace="swarm",this.specificInputSchema=Y,this.bee=t,this.config=r}async executeQuery(e){const{postageBatchId:t,duration:r,size:o}=e;if(!t)throw this.logger.error("Missing required parameter: postageBatchId."),new Error("Missing required parameter: postageBatchId.");if(!r&&!o)throw this.logger.error("You need at least one parameter from duration and size."),new Error("You need at least one parameter from duration and size.");const s=o?a.Size.fromMegabytes(o):a.Size.fromBytes(1);let n,i=a.Duration.ZERO;try{r&&(i=a.Duration.fromMilliseconds(U(r)))}catch(c){throw this.logger.error("Invalid parameter: duration."),new Error("Invalid parameter: duration.")}try{n=await this.bee.extendStorage(t,s,i)}catch(l){let e="Extend failed.";throw D(l,P)?e=N:D(l,O)&&(e=H(l)),this.logger.error(e,l),new Error(e)}return z({postageBatchId:n.toHex()})}}const ee=o.z.object({tagId:o.z.string()});class te extends e.BaseHederaQueryTool{constructor(e){const{bee:t,config:r,...o}=e;super(o),this.name="swarm-query-upload-progress",this.description="Query upload progress for a specific upload session identified with the returned Tag ID.\n tagId: Tag ID returned by swarm-upload-file and swarm-upload-folder tools to track upload progress.\n ",this.namespace="swarm",this.specificInputSchema=ee,this.bee=t,this.config=r}async executeQuery(e){if(!e?.tagId)throw this.logger.error("Missing required parameter: tagId."),new Error("Missing required parameter: tagId.");const t=Number.parseInt(e.tagId,10);if(Number.isNaN(t))throw this.logger.error("Invalid tagId format. Expected a numeric string."),new Error("Invalid tagId format. Expected a numeric string.");try{const e=await this.bee.retrieveTag(t),r=e.synced??0,o=r+(e.seen??0),s=e.split??0,n=e.startedAt,i=s>0?Math.round(o/s*100):0,a=100===i;let c=!1;if(a)try{await this.bee.deleteTag(t),c=!0}catch{}return z({processedPercentage:i,message:a?"Upload completed successfully.":`Upload progress: ${i}% processed`,startedAt:n,tagAddress:e.address})}catch(r){let t=`Failed to retrieve upload progress: ${r?.message??"Unknown error"}`;throw 404===(r?.status??r?.response?.status)&&(t=`Tag with ID ${e.tagId} does not exist or has been deleted. `+L),this.logger.error(t,r),new Error(t)}}}const re=o.z.object({reference:o.z.string(),filePath:o.z.string().optional()});class oe extends e.BaseHederaQueryTool{constructor(e){const{bee:t,config:r,...o}=e;super(o),this.name="swarm-download-files",this.description="Download folder, files from a Swarm reference and save to file path or return file list of the reference.\n Prioritizes this tool over swarm-download-data if there is no assumption about the data type.\n reference: Swarm reference hash.\n filePath: Optional file path to save the downloaded content (only available in stdio mode). If not provided list of files in the manifest will be returned.\n ",this.namespace="swarm",this.specificInputSchema=re,this.bee=t,this.config=r}async executeQuery(e){const{reference:t,filePath:r}=e;if(!t)throw this.logger.error("Missing required parameter: reference."),new Error("Missing required parameter: reference.");this.logger.info(`[API] Downloading folder from Swarm with reference: ${t}.`);let o,s=!1;try{o=await a.MantarayNode.unmarshal(this.bee,t),await o.loadRecursively(this.bee),s=!0}catch(n){}if(s){if(r){const e=r;c.existsSync(e)||await g.promisify(c.mkdir)(e,{recursive:!0});const s=o.collect();if(1===s.length){const t=s[0],r=await this.bee.downloadData(t.targetAddress);await g.promisify(c.writeFile)(l.join(e,t.fullPathString.split("\\").slice(-1)[0]),r.toUint8Array())}else for(const t of s){const r=l.parse(t.fullPathString),o=l.join(e,r.dir);c.existsSync(o)||await g.promisify(c.mkdir)(o,{recursive:!0});const s=await this.bee.downloadData(t.targetAddress);await g.promisify(c.writeFile)(l.join(e,t.fullPathString),s.toUint8Array())}return{content:[{type:"text",text:JSON.stringify({reference:t,manifestNodeCount:s.length,savedTo:e,message:`Manifest content (${s.length} files) successfully downloaded to ${e}`},null,2)}]}}{const e=o.collect().map(e=>({path:e.fullPathString||"/",targetAddress:Array.from(e.targetAddress).map(e=>e.toString(16).padStart(2,"0")).join(""),metadata:e.metadata}));return{content:[{type:"text",text:JSON.stringify({reference:t,type:"manifest",files:e,message:"This is a manifest with multiple files. Provide a filePath to download all files or download individual files using their specific references."},null,2)}]}}}return"Try swarm-download-data tool instead since the given reference is not a manifest."}}const se=o.z.object({postageBatchId:o.z.string()});class ne extends e.BaseHederaQueryTool{constructor(e){const{bee:t,config:r,...o}=e;super(o),this.name="swarm-get-postage-stamp",this.description="Get a specific postage stamp based on postageBatchId.\n postageBatchId: The id of the stamp which is requested.\n ",this.namespace="swarm",this.specificInputSchema=se,this.bee=t,this.config=r}async executeQuery(e){const{postageBatchId:t}=e;if(!t)throw this.logger.error("Missing required parameter: postageBatchId."),new Error("Missing required parameter: postageBatchId.");let r;try{r=await this.bee.getPostageBatch(t)}catch(n){let e="Retrieval of postage batch failed.";throw D(n,P)&&(e=N),this.logger.error(e,n),new Error(e)}const o={...r,batchID:r.batchID.toHex()},s=B(r);return z({raw:o,summary:s})}}const ie=o.z.object({memoryTopic:o.z.string(),owner:o.z.string().optional()});class ae extends e.BaseHederaQueryTool{constructor(e){const{bee:t,config:r,...o}=e;super(o),this.name="swarm-read-feed",this.description="Retrieve the latest data from the feed of a given topic.\n memoryTopic: Feed topic.\n owner: When accessing external memory or feed, ethereum address of the owner must be set.\n ",this.namespace="swarm",this.specificInputSchema=ie,this.bee=t,this.config=r}async executeQuery(e){const{memoryTopic:t,owner:r}=e;if(!t)throw this.logger.error("Missing required parameter: memoryTopic."),new Error("Missing required parameter: memoryTopic.");if(this.logger.info(`[API] Downloading text from Swarm feed with topic: ${t}.`),!this.config.beeFeedPK)throw this.logger.error("Feed private key not configured."),new Error("Feed private key not configured.");let o=t;o.startsWith("0x")&&(o=o.slice(2));if(!/^[0-9a-fA-F]{64}$/.test(o)){o=u.createHash("sha256").update(t).digest("hex")}const s=$(o);let n,i=r;if(i){if(i.startsWith("0x")&&(i=i.slice(2)),40!==i.length)throw this.logger.error("Owner must be a valid Ethereum address."),new Error("Owner must be a valid Ethereum address.")}else{const e=$(this.config.beeFeedPK);i=new h.Wallet(e).getAddressString().slice(2)}try{const e=this.bee.makeFeedReader(s,i);n=(await e.downloadPayload()).payload.toUtf8()}catch(a){let e="Reading feed failed.";throw D(a,O)&&(e=H(a)),this.logger.error(e,a),new Error(e)}return z({textData:n})}}const ce=o.z.object({data:o.z.string(),memoryTopic:o.z.string(),postageBatchId:o.z.string().optional()});class le extends e.BaseHederaQueryTool{constructor(e){const{bee:t,config:r,...o}=e;super(o),this.name="swarm-update-feed",this.description="Update the feed of a given topic with new data.\n data: Arbitrary string to upload.\n memoryTopic: If provided, uploads the data to a feed with this topic. It is the label of the memory that can be used later to retrieve the data instead of its content hash. If not a hex string, it will be hashed to create a feed topic.\n postageBatchId: The postage stamp batch ID which will be used to perform the upload, if it is provided.",this.namespace="swarm",this.specificInputSchema=ce,this.bee=t,this.config=r}async executeQuery(e){const{data:t,memoryTopic:r,postageBatchId:o}=e;if(!t)throw this.logger.error("Missing required parameter: data."),new Error("Missing required parameter: data.");if(!r)throw this.logger.error("Missing required parameter: topic."),new Error("Missing required parameter: topic.");let s="";try{s=await j(o,this.bee,this.config)}catch(m){let e="Update feed failed.";throw m instanceof Error&&(e=m.message),this.logger.error(e),new Error(e)}const n=globalThis.Buffer.from(t);if(!this.config.beeFeedPK)throw this.logger.error("Feed private key not configured."),new Error("Feed private key not configured.");let i=r;i.startsWith("0x")&&(i=i.slice(2));if(!/^[0-9a-fA-F]{64}$/.test(r)){i=u.createHash("sha256").update(r).digest("hex")}const a=$(i),c=$(this.config.beeFeedPK),l=new h.Wallet(c).getAddressString().slice(2);let g;try{const e=this.bee.makeFeedWriter(a,c);g=await e.uploadPayload(s,n)}catch(m){let e="Unable to update feed.";throw D(m,O)&&(e=H(m)),this.logger.error(e,m),new Error(e)}const d=g.reference.toString();return z({reference:d,topicString:r,topic:i,feedUrl:`${this.bee.url}/feeds/${l}/${i}`,message:"Data successfully uploaded to Swarm and linked to feed."})}}const ge=o.z.object({data:o.z.string(),isPath:o.z.boolean(),redundancyLevel:o.z.number().optional(),postageBatchId:o.z.string().optional()});class he extends e.BaseHederaQueryTool{constructor(e){const{bee:t,config:r,...o}=e;super(o),this.name="swarm-upload-file",this.description="Upload a file to Swarm.\n data: base64 encoded file content or file path.\n isPath: Wether the data parameter is a path.\n redundancyLevel: Redundancy level for fault tolerance (higher values provide better fault tolerance but increase storage overhead). 0 - none, 1 - medium, 2 - strong, 3 - insane, 4 - paranoid.\n postageBatchId: The postage stamp batch ID which will be used to perform the upload, if it is provided.",this.namespace="swarm",this.specificInputSchema=ge,this.bee=t,this.config=r}async executeQuery(e){const{data:t,isPath:r,redundancyLevel:o,postageBatchId:s}=e;if(!t)throw this.logger.error("Missing required parameter: data."),new Error("Missing required parameter: data.");let n,i,a="";try{a=await j(s,this.bee,this.config)}catch(y){let e="Upload file failed.";throw y instanceof Error&&(e=y.message),this.logger.error(e),new Error(e)}if(r){try{n=await g.promisify(c.readFile)(t)}catch(w){throw this.logger.error(`Unable to read file at path: ${t}.`,w),new Error(`Unable to read file at path: ${t}.`)}i=t.split("/").pop()}else n=globalThis.Buffer.from(t,"base64");const l=o,h={},u=Number(this.config.deferredUploadSizeThresholdMB)||5,d=n.length>1024*u*1024;h.deferred=d,l&&(h.redundancyLevel=l);let m,p,f="File successfully uploaded to Swarm";if(d)try{const e=await this.bee.createTag();h.tag=e.uid,m=e.uid.toString(),f="File upload started in deferred mode. Use query_upload_progress to track progress."}catch(y){if(D(y,P))throw this.logger.error(L,y),new Error(L)}try{p=await this.bee.uploadFile(a,n,i,h)}catch(y){let e="Unable to upload file.";throw D(y,O)&&(e=H(y)),this.logger.error(e,y),new Error(e)}return z({reference:p.reference.toString(),url:this.bee.url+"/bzz/"+p.reference.toString(),message:f,tagId:m})}}const ue=o.z.object({folderPath:o.z.string(),redundancyLevel:o.z.number().optional(),postageBatchId:o.z.string().optional()});class de extends e.BaseHederaQueryTool{constructor(e){const{bee:t,config:r,...o}=e;super(o),this.name="swarm-upload-folder",this.description="Upload a folder to Swarm.\n folderPath: Path to the folder to upload. \n redundancyLevel: Redundancy level for fault tolerance (higher values provide better fault tolerance but increase storage overhead). 0 - none, 1 - medium, 2 - strong, 3 - insane, 4 - paranoid. \n postageBatchId: The postage stamp batch ID which will be used to perform the upload, if it is provided.",this.namespace="swarm",this.specificInputSchema=ue,this.bee=t,this.config=r}async executeQuery(e){const{folderPath:t,redundancyLevel:r,postageBatchId:o}=e;if(!t)throw this.logger.error("Missing required parameter: folderPath."),new Error("Missing required parameter: folderPath.");if(!(await g.promisify(c.stat)(t)).isDirectory())throw this.logger.error(`Path is not a directory: ${t}.`),new Error(`Path is not a directory: ${t}.`);let s="";try{s=await j(o,this.bee,this.config)}catch(u){let e="Upload folder failed.";throw u instanceof Error&&(e=u.message),this.logger.error(e),new Error(e)}const n=r,i={};n&&(i.redundancyLevel=n);i.deferred=!0;let a,l,h="Folder successfully uploaded to Swarm";try{const e=await this.bee.createTag();a=e.uid.toString(),i.tag=e.uid,h="Folder upload started in deferred mode. Use swarm-query-upload-progress to track progress."}catch(u){this.logger.error("Failed to create tag",u),i.deferred=!1}try{l=await this.bee.uploadFilesFromDirectory(s,t,i)}catch(u){let e="Unable to upload folder.";throw D(u,O)&&(e=H(u)),this.logger.error(e,u),new Error(e)}return z({reference:l.reference.toString(),url:this.bee.url+"/bzz/"+l.reference.toString(),message:h,tagId:a})}}class me extends e.BasePlugin{constructor(e){super(),this.id="swarm",this.name="Swarm Plugin",this.description="Swarm operations: tools for interacting with the Swarm decentralized storage.",this.version="1.0.0",this.author="Solar Punk",this.namespace="swarm",this.tools=[],this.config=e||null}async initialize(e){await super.initialize(e);const t=e.config.hederaKit;if(!t)return this.context.logger.warn("SwarmPlugin skipped because HederaAgentKit was not present in plugin context."),void(this.tools=[]);if(!this.config)return this.context.logger.warn("SwarmPlugin skipped because Swarm config was not present."),void(this.tools=[]);const r=this.config.beeApiUrl,o=new a.Bee(r),s=new X({hederaKit:t,bee:o,config:this.config,logger:this.context.logger}),n=new V({hederaKit:t,bee:o,config:this.config,logger:this.context.logger}),i=new oe({hederaKit:t,bee:o,config:this.config,logger:this.context.logger}),c=new Q({hederaKit:t,bee:o,config:this.config,logger:this.context.logger}),l=new ne({hederaKit:t,bee:o,config:this.config,logger:this.context.logger}),g=new K({hederaKit:t,bee:o,config:this.config,logger:this.context.logger}),h=new te({hederaKit:t,bee:o,config:this.config,logger:this.context.logger}),u=new ae({hederaKit:t,bee:o,config:this.config,logger:this.context.logger}),d=new le({hederaKit:t,bee:o,config:this.config,logger:this.context.logger}),m=new W({hederaKit:t,bee:o,config:this.config,logger:this.context.logger}),p=new he({hederaKit:t,bee:o,config:this.config,logger:this.context.logger}),f=new de({hederaKit:t,bee:o,config:this.config,logger:this.context.logger});this.tools=[s,n,i,c,l,g,h,u,d,m,p,f],this.context.logger.info("Swarm Plugin initialized.")}getTools(){return this.tools}async cleanup(){this.tools=[]}}class pe{constructor(){this.patterns=new Map,this.initializeDefaultPatterns()}static getInstance(){return pe.instance||(pe.instance=new pe),pe.instance}initializeDefaultPatterns(){this.register("numeric-supply-exact",{pattern:["maxSupply","minSupply","totalSupply"],type:"number",priority:15}),this.register("numeric-supply",{pattern:/supply$/i,type:"number",priority:10}),this.register("numeric-amounts",{pattern:/(?:amount|quantity|count|total|sum|value)$/i,type:"number",priority:8}),this.register("numeric-time",{pattern:/(?:period|duration|time|timeout|delay|interval)$/i,type:"number",priority:8}),this.register("numeric-limits",{pattern:/(?:limit|max|min|threshold|size|length)$/i,type:"number",priority:7}),this.register("currency",{pattern:/(?:price|cost|fee|payment|balance|amount)$/i,type:"currency",priority:9}),this.register("percentage",{pattern:/(?:percent|percentage|rate|ratio)$/i,type:"percentage",priority:9}),this.register("boolean-freeze",{pattern:["freezeDefault","freeze"],type:"checkbox",priority:10}),this.register("boolean-flags",{pattern:/(?:is|has|can|should|enable|disable|active|default|allow)(?:[A-Z]|$)/,type:"checkbox",priority:8}),this.register("textarea",{pattern:/(?:memo|description|notes|comment|message|content|body|text)$/i,type:"textarea",priority:8}),this.register("array-fees",{pattern:["customFees","fees"],type:"array",priority:10}),this.register("array-general",{pattern:/(?:list|items|array|collection)$/i,type:"array",priority:7}),this.register("object-options",{pattern:["metaOptions","options"],type:"object",priority:10}),this.register("object-config",{pattern:/(?:config|settings|configuration|metadata|data|info)$/i,type:"object",priority:7}),this.register("select-type",{pattern:/(?:type|kind|category|status|state|mode)$/i,type:"select",priority:7})}register(e,t){this.patterns.set(e,t)}unregister(e){return this.patterns.delete(e)}detectType(e){const t=[];for(const r of this.patterns.values()){let o=!1;Array.isArray(r.pattern)?o=r.pattern.some(t=>e===t||e.toLowerCase()===t.toLowerCase()):r.pattern instanceof RegExp&&(o=r.pattern.test(e)),o&&t.push({type:r.type,priority:r.priority??5})}return t.length>0?(t.sort((e,t)=>t.priority-e.priority),t[0].type):null}getPatterns(){return new Map(this.patterns)}clear(){this.patterns.clear()}reset(){this.clear(),this.initializeDefaultPatterns()}}const fe=pe.getInstance(),ye="Too many requests. Please wait a moment and try again.",we="I'm receiving too many requests right now. Please wait a moment and try again.";var be=(e=>(e.TOPIC_ID="topicId",e.HRL="hrl",e.SCHEDULE_ID="scheduleId",e.TOKEN_ID="tokenId",e.ADDRESS="address",e.SYMBOL="symbol",e.SERIAL_NUMBER="serialNumber",e.METADATA="metadata",e.ACCOUNT_ID="accountId",e.ALIAS="alias",e.EVM_ADDRESS="evmAddress",e.CONTRACT_ID="contractId",e.FILE_ID="fileId",e.ANY="any",e))(be||{});const Te="the topic",Se="the token";be.TOPIC_ID,be.TOKEN_ID,be.ACCOUNT_ID,be.CONTRACT_ID;const ve={ESSENTIAL:"essential",COMMON:"common",ADVANCED:"advanced",EXPERT:"expert"};function ke(e){return"object"==typeof e&&null!==e&&"shape"in e}class Ce{constructor(){this.logger=new r.Logger({module:"FormGenerator"})}generateFormFromError(e,t,r,o){const s=this.extractValidationErrors(e),n=this.identifyMissingFields(s,t),i=this.createFormConfig(t,n,r);return{type:"form",id:`form_${Date.now()}_${Math.random().toString(36).substr(2,9)}`,formConfig:i,originalPrompt:o,toolName:r,validationErrors:s}}async generateFormFromSchema(e,t,r,o){let s;if(this.logger.info("🏁 FormGenerator.generateFormFromSchema starting",{toolName:r.toolName,partialInput:t,hasSchema:!!e,hasShape:!(!e||!ke(e)),hasPreCalculatedFields:void 0!==o,preCalculatedFieldsSize:o?.size||0}),void 0!==o)s=o,this.logger.info("📋 Using pre-calculated missing fields",{missingFieldsCount:s.size,missingFields:Array.from(s)});else{s=new Set;const t=this.extractZodObject(e);if(t){const e=t.shape;for(const t of Object.keys(e))s.add(t),this.logger.info(`⭐ Including all fields from focused schema: ${t}`)}this.logger.info("📋 Using ALL fields from focused schema",{totalFields:t?Object.keys(t.shape).length:0,missingFieldsCount:s.size,missingFields:Array.from(s)})}const n=this.createFormConfig(e,s,r.toolName,o);return{type:"form",id:`form_${Date.now()}_${Math.random().toString(36).substr(2,9)}`,formConfig:n,originalPrompt:r.toolDescription||`Complete ${r.toolName}`,toolName:r.toolName,validationErrors:[]}}extractValidationErrors(e){return e.issues.map(e=>({path:e.path.map(e=>String(e)),message:e.message,code:e.code}))}identifyMissingFields(e,t){const r=new Set;return e.forEach(e=>{const t=e.path.join(".");t&&r.add(t)}),r}createFormConfig(e,t,r,o){const s=this.extractRenderConfigsSafely(e),n=this.generateFieldOrderingSafely(e),i=this.generateFormFields(e,s,t,n,o,r),a=C.getGlobalGuidance(r);let c=this.generateFormDescription(r,t.size);return a?.qualityStandards&&(c+="\n\nQuality Guidelines:\n"+a.qualityStandards.map(e=>`• ${e}`).join("\n")),{title:this.generateFormTitle(r),description:c,fields:i,submitLabel:"Continue",cancelLabel:"Cancel",metadata:{toolName:r,missingFieldCount:t.size,globalGuidance:a}}}extractRenderConfigsSafely(e){try{if("function"==typeof t.extractRenderConfigs)return t.extractRenderConfigs(e)}catch(r){this.logger.warn("Could not extract render configs:",r)}return{fields:{},groups:{},order:[],metadata:{}}}generateFieldOrderingSafely(e){try{if("function"==typeof t.generateFieldOrdering){const r=t.generateFieldOrdering(e);return{sections:Object.values(r.sections).map(e=>({fields:e.fields}))}}}catch(r){this.logger.warn("Could not generate field ordering:",r)}return{sections:[]}}getFieldPriority(e,t,r){if(t?.ui?.priority){const e=t.ui.priority;if(Object.values(ve).includes(e))return e}if(!0===r)return ve.ESSENTIAL;const o=t?.ui;return!0===o?.advanced?ve.ADVANCED:!0===o?.expert?ve.EXPERT:ve.COMMON}determineFieldsToInclude(e,t,r){const o=new Set;if(void 0===r){this.logger.info("⭐ Focused schema mode - including ALL fields from schema");this.extractFieldsFromSchema(e).forEach(e=>{o.add(e),this.logger.info(`✅ Including focused schema field: ${e}`)})}else r.size>0?(this.logger.info(`📋 Using ONLY pre-calculated missing fields (${r.size} fields)`,{fields:Array.from(r)}),r.forEach(e=>{o.add(e),this.logger.info(`✅ Including pre-calculated field: ${e}`)})):(this.logger.info("⚠️ No pre-calculated fields, falling back to schema analysis"),this.includeRequiredMissingFields(e,t,o));return o}includeRequiredMissingFields(e,t,r){this.extractFieldsFromSchema(e).forEach(o=>{const s=this.isFieldRequired(e,o),n=t.has(o),i=n&&s;this.logger.info(`🔍 FormGenerator field inclusion check: ${o}`,{isRequired:s,isMissing:n,shouldInclude:i}),i&&r.add(o)})}createOrderedFields(e,t,r,o,s){const n=[],i=new Set;if(t.sections.length>0){t.sections.flatMap(e=>e.fields).forEach(t=>{if(e.has(t)&&!i.has(t)){const e=this.createFormField(t,r.fields[t],o,t,s);e&&(n.push(e),i.add(t))}})}return e.forEach(e=>{if(!i.has(e)){const t=this.createFormField(e,r.fields[e],o,e,s);t&&n.push(t)}}),n}generateFormFields(e,t,r,o,s,n){const i=this.determineFieldsToInclude(e,r,s);let a=this.createOrderedFields(i,o,t,e,n);return 0===a.length&&r.size>0&&(a=Array.from(r).map(r=>this.createFormField(r,t.fields[r],e,r,n)).filter(e=>null!=e)),a}createFormField(e,t,r,o,s){const n=this.mapFieldType(t?.fieldType,r,o),i=this.isFieldRequired(r,o||e),a=s?C.getFieldGuidance(s,e):null,c=a?.fieldTypeOverride||n,l={name:e,label:t?.ui?.label||this.humanizeFieldName(e),type:c,required:i,priority:this.getFieldPriority(e,t,i)};if(a&&(a.suggestions&&a.suggestions.length>0&&(l