hybrid 1.2.2 → 1.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/core/agent.ts","../src/lib/render.ts","../src/server/listen.ts","../src/xmtp/plugin.ts","../src/server/processor.ts","../src/lib/jwt.ts","../src/core/plugin.ts","../src/core/tool.ts"],"sourcesContent":["import { randomUUID } from \"@hybrd/utils\"\nimport {\n\tLanguageModel,\n\tTelemetrySettings,\n\tUIMessage,\n\tUIMessageStreamOnFinishCallback,\n\tconvertToModelMessages,\n\tgenerateText,\n\tsmoothStream,\n\tstepCountIs,\n\tstreamText\n} from \"ai\"\nimport { z } from \"zod\"\nimport { render } from \"../lib/render\"\nimport type { PluginContext } from \"../server/listen\"\nimport { ListenOptions, listen } from \"../server/listen\"\nimport type { AgentRuntime } from \"../types\"\nimport type { Plugin } from \"./plugin\"\nimport { PluginRegistry } from \"./plugin\"\nimport { Tool, toAISDKTools } from \"./tool\"\n\nexport type DefaultRuntimeExtension = Record<string, never>\n\n/**\n * Tool that can be used in Agent configuration.\n * Extends the base Tool type with runtime extension support.\n */\ntype AgentTool<TRuntimeExtension = DefaultRuntimeExtension> = Tool<\n\tz.ZodTypeAny,\n\tz.ZodTypeAny,\n\tTRuntimeExtension\n>\n\n/**\n * Function that generates tools dynamically based on messages and runtime context.\n * Allows for context-aware tool selection and configuration.\n */\nexport type ToolGenerator<TRuntimeExtension = DefaultRuntimeExtension> =\n\t(props: {\n\t\tmessages: UIMessage[]\n\t\truntime: AgentRuntime & TRuntimeExtension\n\t}) =>\n\t\t| Record<string, AgentTool<TRuntimeExtension>>\n\t\t| Promise<Record<string, AgentTool<TRuntimeExtension>>>\n\n/**\n * Configuration interface for creating an Agent instance.\n * Supports both static and dynamic configuration through functions.\n */\nexport interface AgentConfig<TRuntimeExtension = DefaultRuntimeExtension> {\n\t/** Unique identifier for the agent */\n\tname: string\n\t/** Language model to use, can be static or dynamically resolved */\n\tmodel:\n\t\t| LanguageModel\n\t\t| ((props: {\n\t\t\t\truntime: AgentRuntime & TRuntimeExtension\n\t\t }) => LanguageModel | Promise<LanguageModel>)\n\t/** Tools available to the agent, can be static or dynamically generated */\n\ttools?:\n\t\t| Record<string, AgentTool<TRuntimeExtension>>\n\t\t| ToolGenerator<TRuntimeExtension>\n\t/** Instructions for the agent, can be static or dynamically resolved */\n\tinstructions:\n\t\t| string\n\t\t| ((props: {\n\t\t\t\tmessages: UIMessage[]\n\t\t\t\truntime: AgentRuntime & TRuntimeExtension\n\t\t }) => string | Promise<string>)\n\t/** Function to create the runtime extension, type will be inferred */\n\tcreateRuntime?: (\n\t\truntime: AgentRuntime\n\t) => TRuntimeExtension | Promise<TRuntimeExtension>\n\t/** Optional metadata for the agent */\n\tmetadata?: Record<string, unknown>\n\t/** Maximum number of steps the agent can take */\n\tmaxSteps?: number\n\t/** Maximum tokens for generation */\n\tmaxTokens?: number\n\t/** Temperature for generation (0.0 to 2.0) */\n\ttemperature?: number\n}\n\n/**\n * Options for text generation with the agent.\n * Extends AI SDK parameters while adding agent-specific options.\n */\nexport interface GenerateOptions<TRuntimeExtension = DefaultRuntimeExtension>\n\textends Omit<\n\t\tParameters<typeof generateText>[0],\n\t\t\"model\" | \"tools\" | \"instructions\" | \"onFinish\"\n\t> {\n\t/** Maximum tokens for generation */\n\tmaxTokens?: number\n\t/** Runtime context for the agent */\n\truntime: AgentRuntime & TRuntimeExtension\n\t/** Optional telemetry configuration */\n\ttelemetry?: NonNullable<TelemetrySettings>\n}\n\n/**\n * Options for streaming text with the agent.\n * Extends AI SDK parameters while adding agent-specific options.\n */\nexport interface StreamOptions<TRuntimeExtension = DefaultRuntimeExtension>\n\textends Omit<\n\t\tParameters<typeof streamText>[0],\n\t\t\"model\" | \"tools\" | \"instructions\" | \"onFinish\"\n\t> {\n\t/** Maximum tokens for generation */\n\tmaxTokens?: number\n\t/** Runtime context for the agent */\n\truntime: AgentRuntime & TRuntimeExtension\n\t/** Optional telemetry configuration */\n\ttelemetry?: NonNullable<TelemetrySettings>\n\t/** Callback when streaming finishes */\n\tonFinish?: UIMessageStreamOnFinishCallback<UIMessage>\n}\n\n/**\n * Core Agent implementation using AI SDK 5 directly.\n * This class provides a flexible interface for creating AI agents with\n * dynamic configuration, tool support, and streaming capabilities.\n */\nexport class Agent<TRuntimeExtension = DefaultRuntimeExtension> {\n\t/** Agent's unique identifier */\n\tpublic readonly name: string\n\t/** Optional description of the agent */\n\tpublic readonly description?: string\n\t/** Optional metadata associated with the agent */\n\tpublic readonly metadata?: Record<string, unknown>\n\t/** Agent configuration */\n\tprivate readonly config: AgentConfig<TRuntimeExtension>\n\t/** Default parameters for text generation */\n\tprivate readonly generationDefaults: Partial<\n\t\tPick<\n\t\t\tParameters<typeof generateText>[0],\n\t\t\t| \"model\"\n\t\t\t| \"messages\"\n\t\t\t| \"tools\"\n\t\t\t| \"toolChoice\"\n\t\t\t| \"stopWhen\"\n\t\t\t| \"maxOutputTokens\"\n\t\t\t| \"temperature\"\n\t\t>\n\t>\n\t/** Default parameters for text streaming */\n\tprivate readonly streamDefaults: Partial<\n\t\tPick<\n\t\t\tParameters<typeof streamText>[0],\n\t\t\t| \"model\"\n\t\t\t| \"messages\"\n\t\t\t| \"tools\"\n\t\t\t| \"toolChoice\"\n\t\t\t| \"stopWhen\"\n\t\t\t| \"experimental_transform\"\n\t\t\t| \"maxOutputTokens\"\n\t\t\t| \"temperature\"\n\t\t>\n\t>\n\t/** Plugin registry for extending the agent's HTTP server */\n\tpublic readonly plugins: PluginRegistry<PluginContext>\n\n\t/**\n\t * Creates a new Agent instance with the specified configuration.\n\t * @param config - Configuration object for the agent\n\t */\n\tconstructor(config: AgentConfig<TRuntimeExtension>) {\n\t\tthis.name = config.name\n\t\tthis.metadata = config.metadata\n\t\tthis.config = config\n\t\tthis.plugins = new PluginRegistry<PluginContext>()\n\n\t\tthis.generationDefaults = {\n\t\t\tmaxOutputTokens: config.maxTokens,\n\t\t\ttemperature: config.temperature\n\t\t}\n\n\t\tthis.streamDefaults = {\n\t\t\tmaxOutputTokens: config.maxTokens,\n\t\t\ttemperature: config.temperature\n\t\t}\n\t}\n\n\t/**\n\t * Resolves dynamic configuration properties (model, tools, instructions) with runtime context.\n\t * @param messages - Current conversation messages\n\t * @param runtime - Runtime context for the agent\n\t * @returns Resolved configuration with model, tools, and instructions\n\t */\n\tprivate async resolveConfig(\n\t\tmessages: UIMessage[],\n\t\truntime: AgentRuntime & TRuntimeExtension\n\t): Promise<{\n\t\tmodel: LanguageModel\n\t\ttools?: Record<string, Tool<z.ZodTypeAny, z.ZodTypeAny, TRuntimeExtension>>\n\t\tinstructions?: string\n\t}> {\n\t\tconst props = { messages, runtime }\n\n\t\tconst model =\n\t\t\ttypeof this.config.model === \"function\"\n\t\t\t\t? await this.config.model(props)\n\t\t\t\t: this.config.model\n\n\t\tconst tools =\n\t\t\ttypeof this.config.tools === \"function\"\n\t\t\t\t? await this.config.tools(props)\n\t\t\t\t: this.config.tools\n\n\t\tconst instructions =\n\t\t\ttypeof this.config.instructions === \"function\"\n\t\t\t\t? await this.config.instructions(props)\n\t\t\t\t: this.config.instructions\n\n\t\treturn {\n\t\t\tmodel,\n\t\t\ttools,\n\t\t\tinstructions: render(instructions, runtime)\n\t\t}\n\t}\n\n\t/**\n\t * Prepares messages by adding system instructions if provided.\n\t * Merges instructions with existing system messages or creates new ones.\n\t * @param messages - Current conversation messages\n\t * @param instructions - System instructions to add\n\t * @returns Messages with system instructions properly integrated\n\t */\n\tprivate prepareMessages(\n\t\tmessages: UIMessage[],\n\t\tinstructions?: string\n\t): UIMessage[] {\n\t\tif (!instructions) {\n\t\t\treturn messages\n\t\t}\n\n\t\tif (messages[0]?.role === \"system\") {\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\t...messages[0],\n\t\t\t\t\tparts: [{ type: \"text\", text: instructions }]\n\t\t\t\t},\n\t\t\t\t...messages.slice(1)\n\t\t\t]\n\t\t}\n\n\t\treturn [\n\t\t\t{\n\t\t\t\trole: \"system\",\n\t\t\t\tid: randomUUID(),\n\t\t\t\tparts: [{ type: \"text\", text: instructions }]\n\t\t\t},\n\t\t\t...messages\n\t\t]\n\t}\n\n\t/**\n\t * Generates a text completion using the agent's configuration.\n\t * @param messages - Conversation messages to generate from\n\t * @param options - Generation options including runtime context\n\t * @returns Generated text completion result\n\t */\n\tasync generate(\n\t\tmessages: UIMessage[],\n\t\toptions: GenerateOptions<TRuntimeExtension>\n\t) {\n\t\t// Ensure runtime is properly extended with createRuntime function\n\t\tconst extendedRuntime = await this.createRuntimeContext(options.runtime)\n\n\t\tconst { model, tools, instructions } = await this.resolveConfig(\n\t\t\tmessages,\n\t\t\textendedRuntime\n\t\t)\n\n\t\tconst preparedMessages = this.prepareMessages(messages, instructions)\n\n\t\tconst { runtime, maxTokens, telemetry, prompt, ...aiSdkOptions } = options\n\n\t\tconst aiSDKTools = tools\n\t\t\t? toAISDKTools<TRuntimeExtension, z.ZodTypeAny, z.ZodTypeAny>(\n\t\t\t\t\ttools,\n\t\t\t\t\textendedRuntime,\n\t\t\t\t\tpreparedMessages\n\t\t\t\t)\n\t\t\t: undefined\n\n\t\tconst result = await generateText({\n\t\t\t...this.generationDefaults,\n\t\t\t...aiSdkOptions,\n\t\t\tmodel,\n\t\t\tmessages: convertToModelMessages(preparedMessages),\n\t\t\ttools: aiSDKTools,\n\t\t\ttoolChoice:\n\t\t\t\taiSDKTools && Object.keys(aiSDKTools).length > 0 ? \"auto\" : undefined,\n\t\t\tstopWhen: [stepCountIs(this.config.maxSteps ?? 5)],\n\t\t\tmaxOutputTokens: maxTokens\n\t\t})\n\n\t\treturn result\n\t}\n\n\t/**\n\t * Streams a text completion using the agent's configuration.\n\t * @param messages - Conversation messages to generate from\n\t * @param options - Streaming options including runtime context\n\t * @returns Streaming response that can be consumed\n\t */\n\tasync stream(\n\t\tmessages: UIMessage[],\n\t\toptions: StreamOptions<TRuntimeExtension>\n\t) {\n\t\t// Ensure runtime is properly extended with createRuntime function\n\t\tconst extendedRuntime = await this.createRuntimeContext(options.runtime)\n\n\t\tconst { model, tools, instructions } = await this.resolveConfig(\n\t\t\tmessages,\n\t\t\textendedRuntime\n\t\t)\n\n\t\tconst preparedMessages = this.prepareMessages(messages, instructions)\n\n\t\tconst { runtime, onFinish, maxTokens, telemetry, prompt, ...aiSdkOptions } =\n\t\t\toptions\n\n\t\tconst aiSDKTools = tools\n\t\t\t? toAISDKTools<TRuntimeExtension, z.ZodTypeAny, z.ZodTypeAny>(\n\t\t\t\t\ttools,\n\t\t\t\t\textendedRuntime,\n\t\t\t\t\tpreparedMessages\n\t\t\t\t)\n\t\t\t: undefined\n\n\t\tconst result = await streamText({\n\t\t\t...this.streamDefaults,\n\t\t\t...aiSdkOptions,\n\t\t\tmodel,\n\t\t\tmessages: convertToModelMessages(preparedMessages),\n\t\t\ttools: aiSDKTools,\n\t\t\ttoolChoice:\n\t\t\t\taiSDKTools && Object.keys(aiSDKTools).length > 0 ? \"auto\" : undefined,\n\t\t\tstopWhen: [stepCountIs(this.config.maxSteps ?? 5)],\n\t\t\texperimental_transform: smoothStream(),\n\t\t\tmaxOutputTokens: maxTokens\n\t\t})\n\n\t\treturn result.toUIMessageStreamResponse({\n\t\t\toriginalMessages: messages,\n\t\t\tonFinish\n\t\t})\n\t}\n\n\t/**\n\t * Gets the agent's configuration for debugging and inspection.\n\t * @returns Object containing agent configuration details\n\t */\n\tgetConfig() {\n\t\treturn {\n\t\t\tname: this.name,\n\t\t\tdescription: this.description,\n\t\t\tmetadata: this.metadata,\n\t\t\thasModel: !!this.config.model,\n\t\t\thasTools: !!this.config.tools,\n\t\t\thasInstructions: !!this.config.instructions\n\t\t}\n\t}\n\n\t/**\n\t * Gets the agent's instructions without running generation.\n\t * Useful for external integrations that need instructions separately.\n\t * @param options - Options containing runtime context and optional messages\n\t * @returns Resolved instructions string\n\t */\n\tasync getInstructions(options: {\n\t\truntime: AgentRuntime & TRuntimeExtension\n\t\tmessages?: UIMessage[]\n\t}) {\n\t\t// Ensure runtime is properly extended with createRuntime function\n\t\tconst extendedRuntime = await this.createRuntimeContext(options.runtime)\n\n\t\tconst messages = options.messages || []\n\t\tconst props = { messages, runtime: extendedRuntime }\n\n\t\tif (typeof this.config.instructions === \"function\") {\n\t\t\treturn await this.config.instructions(props)\n\t\t}\n\t\treturn this.config.instructions\n\t}\n\n\t/**\n\t * Gets the agent's tools without running generation.\n\t * Useful for external integrations that need tools separately.\n\t * @param options - Options containing runtime context and optional messages\n\t * @returns Resolved tools object\n\t */\n\tasync getTools(options: {\n\t\truntime: AgentRuntime & TRuntimeExtension\n\t\tmessages?: UIMessage[]\n\t}) {\n\t\t// Ensure runtime is properly extended with createRuntime function\n\t\tconst extendedRuntime = await this.createRuntimeContext(options.runtime)\n\n\t\tconst messages = options.messages || []\n\t\tconst props = { messages, runtime: extendedRuntime }\n\n\t\tif (typeof this.config.tools === \"function\") {\n\t\t\treturn await this.config.tools(props)\n\t\t}\n\t\treturn this.config.tools\n\t}\n\n\t/**\n\t * Creates the complete runtime context by merging base runtime with custom extension.\n\t * @param baseRuntime - The base runtime context containing XMTP properties\n\t * @returns Complete runtime context with custom extensions applied\n\t */\n\t/**\n\t * Creates the complete runtime context by merging base runtime with custom extension.\n\t * @param baseRuntime - The base runtime context containing XMTP properties\n\t * @returns Complete runtime context with custom extensions applied\n\t */\n\tasync createRuntimeContext(\n\t\tbaseRuntime: AgentRuntime\n\t): Promise<AgentRuntime & TRuntimeExtension> {\n\t\t// Always start with the default runtime (baseRuntime)\n\t\tlet completeRuntime = { ...baseRuntime } as AgentRuntime & TRuntimeExtension\n\n\t\t// If user provided createRuntime function, extend the default runtime\n\t\tif (this.config.createRuntime) {\n\t\t\tconst userExtension = await this.config.createRuntime(completeRuntime)\n\t\t\tcompleteRuntime = {\n\t\t\t\t...completeRuntime,\n\t\t\t\t...userExtension\n\t\t\t} as AgentRuntime & TRuntimeExtension\n\t\t}\n\n\t\treturn completeRuntime\n\t}\n\n\t/**\n\t * Registers a plugin with the agent\n\t *\n\t * @param plugin - The plugin to register\n\t */\n\tuse(plugin: Plugin<PluginContext>): void {\n\t\tthis.plugins.register(plugin)\n\t}\n\n\t/**\n\t * Starts listening for messages and events using the agent instance.\n\t * @param opts - Configuration options for the listener, excluding the agent property\n\t */\n\tasync listen(opts: Omit<ListenOptions, \"agent\">) {\n\t\tlisten({ ...opts, agent: this as Agent<DefaultRuntimeExtension> })\n\t}\n}\n","import { Eta } from \"eta\"\n\nexport const eta = new Eta({\n\tviews: \"templates\"\n})\n\nexport const render = (template: string, runtime: Record<string, unknown>) => {\n\treturn eta.renderString(template, runtime)\n}\n","import { serve } from \"@hono/node-server\"\nimport { getCloudflareStoragePath } from \"@hybrd/utils\"\nimport type { MessageListenerConfig, XmtpClient } from \"@hybrd/xmtp\"\nimport { type HonoVariables, createXMTPClient } from \"@hybrd/xmtp\"\nimport { Context, Hono, Next } from \"hono\"\nimport type { Agent, DefaultRuntimeExtension } from \"../core/agent\"\nimport type { Plugin } from \"../core/plugin\"\nimport { XMTPPlugin } from \"../xmtp/plugin\"\nimport {\n\tcreateBackgroundMessageProcessor,\n\tgetBgState,\n\tstopBackground\n} from \"./processor\"\n\nexport type { HonoVariables } from \"@hybrd/xmtp\"\n\n/**\n * Creates Hono middleware to inject XMTP client into request context\n *\n * @description\n * This middleware function sets the XMTP client instance in the Hono context,\n * making it available to all subsequent middleware and route handlers.\n * The client can be accessed via `c.get(\"xmtpClient\")` in route handlers.\n *\n * @param client - The XMTP client instance to inject into the context\n * @returns Hono middleware function that sets the XMTP client in context\n *\n * @example\n * ```typescript\n * app.use(createHonoMiddleware(xmtpClient))\n *\n * app.get(\"/messages\", (c) => {\n * const client = c.get(\"xmtpClient\")\n * // Use the client to interact with XMTP\n * })\n * ```\n */\nexport function createHonoMiddleware(client: XmtpClient) {\n\treturn async (c: Context, next: Next) => {\n\t\tc.set(\"xmtpClient\", client)\n\t\treturn next()\n\t}\n}\n\n/**\n * Options for creating a Hono app with XMTP integration\n *\n * @description\n * Configuration object for setting up a Hono application that includes\n * XMTP client middleware, background message processing, and XMTP tools routes.\n *\n * @template TRuntimeExtension - Runtime extension type for the agent\n * @property agent - The agent instance to use for message processing\n */\nexport type CreateHonoAppOptions<TRuntimeExtension = DefaultRuntimeExtension> =\n\t{\n\t\tagent: Agent<TRuntimeExtension>\n\t\tmessageFilter: MessageListenerConfig[\"filter\"]\n\t}\n\n/**\n * Creates a Hono app with full XMTP integration and background message processing\n *\n * @description\n * This function creates a complete Hono application configured with:\n * - XMTP client middleware for request context\n * - Background message processor for handling XMTP messages\n * - XMTP tools routes for external integrations\n * - Environment variable validation for required XMTP credentials\n *\n * The app automatically starts a background message processor that listens for\n * XMTP messages and forwards them to the provided agent for processing.\n *\n * @template TRuntimeExtension - Runtime extension type for the agent\n * @param options - Configuration options for the Hono app\n * @param options.agent - The agent instance to handle XMTP messages\n * @returns Promise that resolves to a configured Hono app instance\n *\n * @throws {Error} When XMTP_WALLET_KEY environment variable is not set\n * @throws {Error} When XMTP_ENCRYPTION_KEY environment variable is not set\n *\n * @example\n * ```typescript\n * const app = await createHonoApp({ agent: myAgent })\n *\n * // The app now has XMTP integration and background processing\n * app.get(\"/health\", (c) => c.json({ status: \"ok\" }))\n * ```\n */\nexport async function createHonoApp<\n\tTRuntimeExtension = DefaultRuntimeExtension\n>({ agent, messageFilter }: CreateHonoAppOptions<TRuntimeExtension>) {\n\tconst app = new Hono<{ Variables: HonoVariables }>()\n\n\tconst { XMTP_WALLET_KEY, XMTP_ENCRYPTION_KEY, XMTP_ENV } = process.env\n\n\tif (!XMTP_WALLET_KEY) {\n\t\tthrow new Error(\"XMTP_WALLET_KEY must be set\")\n\t}\n\n\tif (!XMTP_ENCRYPTION_KEY) {\n\t\tthrow new Error(\"XMTP_ENCRYPTION_KEY must be set\")\n\t}\n\n\t// Create xmtpClient with persistent storage for reliable message streaming\n\tconst cloudflareStoragePath = getCloudflareStoragePath(\"xmtp\")\n\tconst xmtpClient = await createXMTPClient(XMTP_WALLET_KEY as string, {\n\t\tpersist: true,\n\t\tstoragePath: cloudflareStoragePath\n\t})\n\n\t// Apply middleware for XMTP client\n\tapp.use(createHonoMiddleware(xmtpClient))\n\n\t// Start the background message processor\n\tapp.use(\n\t\tcreateBackgroundMessageProcessor({\n\t\t\tagent,\n\t\t\txmtpClient,\n\t\t\tmessageFilter, // Accept all messages by default\n\t\t\tintervalMs: 5_000, // Check every 5 seconds\n\t\t\tbackoffMs: 1_000, // Start with 1 second backoff\n\t\t\tmaxBackoffMs: 30_000 // Max 30 seconds backoff\n\t\t})\n\t)\n\n\t// Mount XMTP tools routes\n\t// app.route(\"/xmtp-tools\", xmtpApp) // This line is removed as per the edit hint\n\n\treturn app\n}\n\n/**\n * Context type for plugins that need agent information\n */\nexport interface PluginContext {\n\tagent: Agent<DefaultRuntimeExtension>\n}\n\n/**\n * Options for starting the XMTP tools HTTP server\n *\n * @description\n * Configuration object for the standalone XMTP tools server that provides\n * basic HTTP endpoints for health checks and XMTP operations.\n *\n * @property agent - The agent instance to associate with the server\n * @property port - The port number to listen on (defaults to 8454)\n * @property filter - Optional message filter for XMTP messages\n * @property plugins - Optional array of plugins to apply to the server\n */\nexport type ListenOptions = {\n\tagent: Agent\n\tport: string\n\tfilter?: MessageListenerConfig[\"filter\"]\n\tplugins?: Plugin<PluginContext>[]\n}\n\n/**\n * Starts a standalone XMTP tools HTTP server\n *\n * @description\n * This function creates and starts a minimal HTTP server specifically for\n * XMTP tools operations. It includes:\n * - Health check endpoint at `/health`\n * - 404 handler for unmatched routes\n * - Automatic port parsing from string input\n * - Plugin-based route mounting\n *\n * The server runs independently and is useful for scenarios where you need\n * XMTP tools functionality without the full Hono app integration.\n *\n * @param options - Configuration options for the server\n * @param options.agent - The agent instance to associate with the server\n * @param options.port - The port number to listen on (parsed as integer)\n *\n * @example\n * ```typescript\n * listen({\n * agent: myAgent,\n * port: \"3000\"\n * })\n *\n * // Server starts on port 3000 with health endpoint at /health\n * // and all registered plugins applied\n * ```\n */\nexport async function listen({\n\tagent,\n\tport,\n\tfilter,\n\tplugins = []\n}: ListenOptions) {\n\tconst app = new Hono<{ Variables: HonoVariables }>()\n\tconst context: PluginContext = {\n\t\tagent\n\t}\n\n\tconst xmtpPlugin = XMTPPlugin({\n\t\tfilter\n\t})\n\n\t// Right now we always apply the XMTP plugin, but this may change in the future.\n\tawait xmtpPlugin.apply(app, context)\n\n\t// Apply plugins from agent registry first\n\tawait agent.plugins.applyAll(app, context)\n\n\t// Apply plugins from listen options\n\tfor (const plugin of plugins) {\n\t\ttry {\n\t\t\tconsole.log(`🔌 Applying plugin: ${plugin.name}`)\n\t\t\tawait plugin.apply(app, context)\n\t\t\tconsole.log(`✅ Plugin applied: ${plugin.name}`)\n\t\t} catch (error) {\n\t\t\tconsole.error(`❌ Failed to apply plugin ${plugin.name}:`, error)\n\t\t\tthrow error\n\t\t}\n\t}\n\n\tapp.get(\"/health\", (c) => {\n\t\treturn c.json({\n\t\t\tstatus: \"healthy\",\n\t\t\tservice: agent.name,\n\t\t\ttimestamp: new Date().toISOString()\n\t\t})\n\t})\n\n\tapp.notFound((c) => {\n\t\treturn c.json({ error: \"Not found\" }, 404)\n\t})\n\n\tserve({\n\t\tfetch: app.fetch,\n\t\tport: Number.parseInt(port || \"8454\")\n\t})\n\n\tconsole.log(`✅ XMTP Tools HTTP Server running`)\n}\n\n// Re-export the background processor helpers\nexport { getBgState, stopBackground }\n","import { MessageListenerConfig } from \"@hybrd/xmtp\"\nimport type { Agent, DefaultRuntimeExtension } from \"../core/agent\"\nimport type { Plugin } from \"../core/plugin\"\nimport { createHonoApp } from \"../server/listen\"\n\n/**\n * Context for the XMTP plugin\n */\nexport interface XMTPPluginContext {\n\tagent: Agent<DefaultRuntimeExtension>\n}\n\n/**\n * XMTP Plugin that provides XMTP functionality to the agent\n *\n * @description\n * This plugin integrates XMTP messaging capabilities into the agent's\n * HTTP server. It creates a Hono app with XMTP client middleware,\n * background message processing, and XMTP tools routes.\n *\n * Note: This plugin requires the agent to be configured with XMTP\n * environment variables and the listen method to be called with a filter.\n */\nexport function XMTPPlugin({\n\tfilter\n}: {\n\tfilter: MessageListenerConfig[\"filter\"]\n}): Plugin<XMTPPluginContext> {\n\treturn {\n\t\tname: \"xmtp\",\n\t\tdescription: \"Provides XMTP messaging functionality\",\n\t\tapply: async (app, context) => {\n\t\t\tif (!context) {\n\t\t\t\tthrow new Error(\"XMTP plugin requires context with agent\")\n\t\t\t}\n\n\t\t\tconst { agent } = context\n\n\t\t\t// Create the XMTP Hono app with a default filter that accepts all messages\n\t\t\t// The actual filter will be applied when the listen method is called\n\t\t\tconst xmtpApp = await createHonoApp({\n\t\t\t\tagent,\n\t\t\t\tmessageFilter: filter\n\t\t\t})\n\n\t\t\t// Mount the XMTP app at the root\n\t\t\tapp.route(\"/\", xmtpApp)\n\t\t}\n\t}\n}\n","import {\n\tMessageEvent,\n\tMessageListener,\n\tMessageListenerConfig,\n\tXmtpClient,\n\tcreateAuthenticatedXmtpClient\n} from \"@hybrd/xmtp\"\nimport { type MiddlewareHandler } from \"hono\"\nimport { randomUUID } from \"node:crypto\"\nimport { createPublicClient, http } from \"viem\"\nimport { base } from \"viem/chains\"\nimport type { Agent } from \"../core/agent\"\nimport { generateXMTPToolsToken } from \"../lib/jwt\"\nimport type { AgentRuntime } from \"../types\"\n\n// Global state management\nconst BG_STARTED = Symbol(\"BG_STARTED\")\nconst BG_STATE = Symbol(\"BG_STATE\")\nconst BG_STOP = Symbol(\"BG_STOP\")\n\ninterface BgState {\n\trunning: boolean\n\tlastStartAt: number\n\tlastOkAt?: number\n\tlastErrAt?: number\n\tconsecutiveErrors: number\n\tmessagesProcessed: number\n\tlistenerRunning: boolean\n}\n\ninterface BackgroundMessageProcessorOptions<\n\tTRuntimeExtension = Record<string, never>\n> {\n\tagent: Agent<TRuntimeExtension>\n\txmtpClient: XmtpClient\n\tmessageFilter: MessageListenerConfig[\"filter\"]\n\tintervalMs?: number\n\tbackoffMs?: number\n\tmaxBackoffMs?: number\n}\n\nfunction sleep(ms: number) {\n\treturn new Promise((r) => setTimeout(r, ms))\n}\n\nexport function createBackgroundMessageProcessor<\n\tTRuntimeExtension = Record<string, never>\n>(\n\topts: BackgroundMessageProcessorOptions<TRuntimeExtension>\n): MiddlewareHandler {\n\tif (!opts?.agent || !opts?.xmtpClient) {\n\t\tthrow new Error(\n\t\t\t\"createBackgroundMessageProcessor: agent and xmtpClient are required\"\n\t\t)\n\t}\n\n\tconst intervalMs = Math.max(250, opts.intervalMs ?? 5_000) // Check every 5 seconds by default\n\tconst baseBackoffMs = Math.max(100, opts.backoffMs ?? 1_000)\n\tconst maxBackoffMs = Math.max(baseBackoffMs, opts.maxBackoffMs ?? 30_000)\n\n\t// Ensure singleton in this process\n\tif (!(globalThis as any)[BG_STARTED]) {\n\t\t;(globalThis as any)[BG_STARTED] = true\n\n\t\tconst state: BgState = {\n\t\t\trunning: true,\n\t\t\tlastStartAt: Date.now(),\n\t\t\tconsecutiveErrors: 0,\n\t\t\tmessagesProcessed: 0,\n\t\t\tlistenerRunning: false\n\t\t}\n\t\t;(globalThis as any)[BG_STATE] = state\n\n\t\tconst ac = new AbortController()\n\t\tconst signal = ac.signal\n\n\t\tconst stop = () => {\n\t\t\tif (!state.running) return\n\t\t\tstate.running = false\n\t\t\tac.abort()\n\t\t\tconsole.log(\"[XMTP Background] Stopping message processor...\")\n\t\t}\n\t\t;(globalThis as any)[BG_STOP] = stop\n\n\t\tprocess.once(\"SIGINT\", stop)\n\t\tprocess.once(\"SIGTERM\", stop)\n\n\t\t// Create public client for address resolution\n\t\tconst publicClient = createPublicClient({\n\t\t\tchain: base,\n\t\t\ttransport: http()\n\t\t})\n\n\t\t// Create message listener - use type assertion to work around viem version differences\n\t\tconst listener = new MessageListener({\n\t\t\tpublicClient: publicClient as any,\n\t\t\txmtpClient: opts.xmtpClient,\n\t\t\tfilter: opts.messageFilter,\n\t\t\theartbeatInterval: 5 * 60 * 1000, // 5 minutes\n\t\t\tconversationCheckInterval: 30 * 1000 // 30 seconds\n\t\t})\n\n\t\t// Set up message event handler\n\t\tlistener.on(\"message\", async (messageEvent: MessageEvent) => {\n\t\t\ttry {\n\t\t\t\tconsole.log(\n\t\t\t\t\t`[XMTP Background] Processing message: ${messageEvent.message.content}`\n\t\t\t\t)\n\t\t\t\tconsole.log(\n\t\t\t\t\t`[XMTP Background] Sender: ${messageEvent.sender?.address || \"unknown\"}`\n\t\t\t\t)\n\t\t\t\tconsole.log(\n\t\t\t\t\t`[XMTP Background] Conversation: ${messageEvent.message.conversationId}`\n\t\t\t\t)\n\n\t\t\t\t// Create a simple message for the agent\n\t\t\t\tconst messages = [\n\t\t\t\t\t{\n\t\t\t\t\t\tid: randomUUID(),\n\t\t\t\t\t\trole: \"user\" as const,\n\t\t\t\t\t\tparts: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttype: \"text\" as const,\n\t\t\t\t\t\t\t\ttext: messageEvent.message.content?.toString() || \"\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t]\n\t\t\t\t\t}\n\t\t\t\t]\n\n\t\t\t\t// Create service client for agent runtime\n\t\t\t\tconst serviceUrl = process.env.AGENT_URL || \"http://localhost:8454\"\n\t\t\t\tconst serviceToken = generateXMTPToolsToken({\n\t\t\t\t\taction: \"send\",\n\t\t\t\t\tconversationId: messageEvent.message.conversationId,\n\t\t\t\t\tcontent: messageEvent.message.content?.toString() || \"\"\n\t\t\t\t})\n\t\t\t\tconst serviceClient = createAuthenticatedXmtpClient(\n\t\t\t\t\tserviceUrl,\n\t\t\t\t\tserviceToken\n\t\t\t\t)\n\n\t\t\t\t// Create base runtime context\n\t\t\t\tconst baseRuntime: AgentRuntime = {\n\t\t\t\t\tchatId: messageEvent.message.conversationId,\n\t\t\t\t\tmessages: messages,\n\t\t\t\t\tconversation: messageEvent.conversation,\n\t\t\t\t\tmessage: messageEvent.message,\n\t\t\t\t\tparentMessage: messageEvent.parentMessage,\n\t\t\t\t\trootMessage: messageEvent.rootMessage,\n\t\t\t\t\tsender: messageEvent.sender,\n\t\t\t\t\tsubjects: messageEvent.subjects,\n\t\t\t\t\txmtpClient: serviceClient\n\t\t\t\t}\n\n\t\t\t\t// Create complete runtime context using agent's createRuntime function\n\t\t\t\tconst runtime = await opts.agent.createRuntimeContext(baseRuntime)\n\n\t\t\t\t// Call the agent to process the message\n\t\t\t\tconsole.log(\"[XMTP Background] Calling agent to process message...\")\n\t\t\t\tconst result = await opts.agent.generate(messages, { runtime })\n\n\t\t\t\tif (result.text) {\n\t\t\t\t\t// Send the response back to the conversation\n\t\t\t\t\tawait messageEvent.conversation.send(result.text)\n\t\t\t\t\tconsole.log(`[XMTP Background] Agent response sent: ${result.text}`)\n\t\t\t\t}\n\n\t\t\t\tstate.messagesProcessed++\n\t\t\t\tstate.lastOkAt = Date.now()\n\t\t\t\tstate.consecutiveErrors = 0\n\n\t\t\t\tconsole.log(\n\t\t\t\t\t`[XMTP Background] Message processed successfully. Total: ${state.messagesProcessed}`\n\t\t\t\t)\n\t\t\t} catch (error) {\n\t\t\t\tstate.lastErrAt = Date.now()\n\t\t\t\tstate.consecutiveErrors++\n\t\t\t\tconsole.error(\"[XMTP Background] Error processing message:\", error)\n\n\t\t\t\t// Try to send an error response\n\t\t\t\ttry {\n\t\t\t\t\tawait messageEvent.conversation.send(\n\t\t\t\t\t\t\"Sorry, I encountered an error processing your message.\"\n\t\t\t\t\t)\n\t\t\t\t} catch (sendError) {\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t\"[XMTP Background] Failed to send error message:\",\n\t\t\t\t\t\tsendError\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\n\t\tlistener.on(\"error\", (error: Error) => {\n\t\t\tstate.lastErrAt = Date.now()\n\t\t\tstate.consecutiveErrors++\n\t\t\tconsole.error(\"[XMTP Background] Message listener error:\", error)\n\t\t})\n\n\t\tlistener.on(\"started\", () => {\n\t\t\tstate.listenerRunning = true\n\t\t\tconsole.log(\"[XMTP Background] Message listener started\")\n\t\t})\n\n\t\tlistener.on(\"stopped\", () => {\n\t\t\tstate.listenerRunning = false\n\t\t\tconsole.log(\"[XMTP Background] Message listener stopped\")\n\t\t})\n\n\t\tlistener.on(\"heartbeat\", (stats) => {\n\t\t\tconsole.log(\n\t\t\t\t`[XMTP Background] Heartbeat - Messages: ${stats.messageCount}, Conversations: ${stats.conversationCount}`\n\t\t\t)\n\t\t})\n\n\t\t// Background supervisor loop\n\t\t;(async function supervise() {\n\t\t\tlet nextDelay = intervalMs\n\n\t\t\twhile (state.running) {\n\t\t\t\ttry {\n\t\t\t\t\t// Start the listener if not already running\n\t\t\t\t\tif (!state.listenerRunning) {\n\t\t\t\t\t\tconsole.log(\"[XMTP Background] Starting message listener...\")\n\t\t\t\t\t\tawait listener.start()\n\t\t\t\t\t}\n\n\t\t\t\t\t// Check listener health\n\t\t\t\t\tif (state.listenerRunning) {\n\t\t\t\t\t\tstate.lastOkAt = Date.now()\n\t\t\t\t\t\tstate.consecutiveErrors = 0\n\t\t\t\t\t\tnextDelay = intervalMs\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthrow new Error(\"Message listener is not running\")\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\tstate.lastErrAt = Date.now()\n\t\t\t\t\tstate.consecutiveErrors += 1\n\t\t\t\t\tconst backoff = Math.min(\n\t\t\t\t\t\tmaxBackoffMs,\n\t\t\t\t\t\tbaseBackoffMs * 2 ** (state.consecutiveErrors - 1)\n\t\t\t\t\t)\n\t\t\t\t\tnextDelay = backoff\n\t\t\t\t\tconsole.error(\"[XMTP Background] Supervisor error:\", error)\n\n\t\t\t\t\t// Try to restart the listener\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (state.listenerRunning) {\n\t\t\t\t\t\t\tawait listener.stop()\n\t\t\t\t\t\t}\n\t\t\t\t\t\tawait sleep(1000) // Wait 1 second before restarting\n\t\t\t\t\t} catch (restartError) {\n\t\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t\t\"[XMTP Background] Error restarting listener:\",\n\t\t\t\t\t\t\trestartError\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Sleep until next iteration\n\t\t\t\tawait sleep(nextDelay)\n\t\t\t}\n\n\t\t\t// Cleanup on exit\n\t\t\ttry {\n\t\t\t\tif (state.listenerRunning) {\n\t\t\t\t\tawait listener.stop()\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\"[XMTP Background] Error stopping listener:\", error)\n\t\t\t}\n\n\t\t\tconsole.log(\"[XMTP Background] Supervisor stopped\")\n\t\t})()\n\n\t\tconsole.log(\n\t\t\t\"[XMTP Background] Message processor started (always-on, in-process)\"\n\t\t)\n\t}\n\n\t// Middleware is a pass-through; registering it ensures the processor is active\n\treturn async (_c, next) => next()\n}\n\n// Optional helpers to inspect/stop from your server code\nexport function getBgState(): BgState | undefined {\n\treturn (globalThis as any)[BG_STATE] as BgState | undefined\n}\n\nexport function stopBackground(): void {\n\tconst fn = (globalThis as any)[BG_STOP] as (() => void) | undefined\n\tif (fn) fn()\n}\n","import { Context } from \"hono\"\nimport jwt from \"jsonwebtoken\"\n\nexport interface XMTPToolsPayload {\n\taction: \"send\" | \"reply\" | \"react\" | \"transaction\" | \"blockchain-event\"\n\tconversationId: string\n\t// Action-specific data\n\tcontent?: string\n\treferenceMessageId?: string\n\temoji?: string\n\tactionType?: \"added\" | \"removed\"\n\tfromAddress?: string\n\tchainId?: string\n\tcalls?: Array<{\n\t\tto: string\n\t\tdata: string\n\t\tmetadata?: {\n\t\t\tdescription: string\n\t\t\ttransactionType: string\n\t\t}\n\t}>\n\t// Metadata\n\tissued: number\n\texpires: number\n}\n\n/**\n * Validates token and returns payload for both GET and POST endpoints\n *\n * @param {Context} c - Hono context object containing request information\n * @returns {XMTPToolsPayload | null} The validated payload or null if invalid\n *\n * @description\n * Supports two authentication methods:\n * - Authorization header with Bearer token (for POST endpoints)\n * - Query parameter token (for GET endpoints)\n *\n * @example\n * ```typescript\n * app.post(\"/api/endpoint\", async (c) => {\n * const payload = getValidatedPayload(c);\n * if (!payload) {\n * return c.json({ error: \"Invalid token\" }, 401);\n * }\n * // Use payload data\n * });\n * ```\n */\nexport function getValidatedPayload(c: Context): XMTPToolsPayload | null {\n\t// Try Authorization header first (for POST endpoints)\n\tconst authHeader = c.req.header(\"Authorization\")\n\tif (authHeader?.startsWith(\"Bearer \")) {\n\t\tconst token = authHeader.substring(7) // Remove \"Bearer \" prefix\n\t\treturn validateXMTPToolsToken(token)\n\t}\n\n\t// Fall back to query parameter (for GET endpoints)\n\tconst token = c.req.query(\"token\")\n\tif (!token) {\n\t\treturn null\n\t}\n\n\treturn validateXMTPToolsToken(token)\n}\n\n/**\n * JWT secret key used for signing and verifying tokens\n * Falls back to a development secret if XMTP_JWT_SECRET is not set\n */\nconst JWT_SECRET = process.env.XMTP_JWT_SECRET || \"fallback-secret-for-dev\"\n\n/**\n * API key used for simple authentication bypass\n * Falls back to a development key if XMTP_API_KEY is not set\n */\nconst API_KEY = process.env.XMTP_API_KEY || \"fallback-api-key-for-dev\"\n\n/**\n * JWT token expiry time in seconds (5 minutes)\n */\nconst JWT_EXPIRY = 5 * 60 // 5 minutes in seconds\n\n/**\n * Generates a signed JWT token for XMTP tools authentication\n *\n * @param {Omit<XMTPToolsPayload, \"issued\" | \"expires\">} payload - Token payload without timestamp fields\n * @returns {string} Signed JWT token\n *\n * @description\n * Creates a JWT token with automatic timestamp fields:\n * - issued: Current timestamp\n * - expires: Current timestamp + JWT_EXPIRY\n *\n * @example\n * ```typescript\n * const token = generateXMTPToolsToken({\n * action: \"send\",\n * conversationId: \"0x123...\"\n * });\n * ```\n */\nexport function generateXMTPToolsToken(\n\tpayload: Omit<XMTPToolsPayload, \"issued\" | \"expires\">\n): string {\n\tconst now = Math.floor(Date.now() / 1000)\n\tconst fullPayload: XMTPToolsPayload = {\n\t\t...payload,\n\t\tissued: now,\n\t\texpires: now + JWT_EXPIRY\n\t}\n\n\treturn jwt.sign(fullPayload, JWT_SECRET, {\n\t\texpiresIn: JWT_EXPIRY\n\t})\n}\n\n/**\n * Validates an XMTP tools token using either API key or JWT verification\n *\n * @param {string} token - Token to validate (either API key or JWT)\n * @returns {XMTPToolsPayload | null} Validated payload or null if invalid\n *\n * @description\n * Supports two authentication methods in order of precedence:\n * 1. API key authentication - Direct comparison with XMTP_API_KEY\n * 2. JWT token authentication - Signature verification and expiry check\n *\n * For API key authentication, returns a default payload with 1-hour expiry.\n * For JWT authentication, validates signature and checks expiry timestamp.\n *\n * @example\n * ```typescript\n * const payload = validateXMTPToolsToken(userToken);\n * if (payload) {\n * console.log(`Action: ${payload.action}`);\n * console.log(`Conversation: ${payload.conversationId}`);\n * }\n * ```\n */\nexport function validateXMTPToolsToken(token: string): XMTPToolsPayload | null {\n\t// First try API key authentication\n\tif (token === API_KEY) {\n\t\tconsole.log(\"🔑 [Auth] Using API key authentication\")\n\t\t// Return a valid payload for API key auth\n\t\tconst now = Math.floor(Date.now() / 1000)\n\t\treturn {\n\t\t\taction: \"send\", // Default action\n\t\t\tconversationId: \"\", // Will be filled by endpoint\n\t\t\tissued: now,\n\t\t\texpires: now + 3600 // API keys are valid for 1 hour\n\t\t}\n\t}\n\n\t// Then try JWT token authentication\n\ttry {\n\t\tconst decoded = jwt.verify(token, JWT_SECRET) as XMTPToolsPayload\n\t\tconsole.log(\"🔑 [Auth] Using JWT token authentication\")\n\n\t\t// Additional expiry check\n\t\tconst now = Math.floor(Date.now() / 1000)\n\t\tif (decoded.expires < now) {\n\t\t\tconsole.warn(\"🔒 XMTP tools token has expired\")\n\t\t\treturn null\n\t\t}\n\n\t\treturn decoded\n\t} catch (error) {\n\t\tconsole.error(\n\t\t\t\"🔒 Invalid XMTP tools token and not matching API key:\",\n\t\t\terror\n\t\t)\n\t\treturn null\n\t}\n}\n","import type { HonoVariables } from \"@hybrd/xmtp\"\nimport type { Hono } from \"hono\"\n\n/**\n * Plugin interface for extending the agent's Hono app\n *\n * @description\n * Plugins allow you to extend the agent's HTTP server with additional\n * routes, middleware, and functionality. Each plugin receives the Hono\n * app instance and can modify it as needed.\n *\n * @template T - Optional context type that can be passed to the plugin\n */\nexport interface Plugin<T = Record<string, never>> {\n\t/**\n\t * Unique identifier for the plugin\n\t */\n\tname: string\n\n\t/**\n\t * Optional description of what the plugin does\n\t */\n\tdescription?: string\n\n\t/**\n\t * Function that applies the plugin to the Hono app\n\t *\n\t * @param app - The Hono app instance to extend\n\t * @param context - Optional context data passed to the plugin\n\t */\n\tapply: (\n\t\tapp: Hono<{ Variables: HonoVariables }>,\n\t\tcontext?: T\n\t) => void | Promise<void>\n}\n\n/**\n * Plugin registry that manages all registered plugins\n *\n * @description\n * The plugin registry allows you to register, configure, and apply\n * plugins to Hono apps. It provides a centralized way to manage\n * plugin dependencies and execution order.\n */\nexport class PluginRegistry<T = Record<string, never>> {\n\tprivate plugins: Map<string, Plugin<T>> = new Map()\n\n\t/**\n\t * Registers a plugin with the registry\n\t *\n\t * @param plugin - The plugin to register\n\t * @throws {Error} If a plugin with the same name is already registered\n\t */\n\tregister(plugin: Plugin<T>): void {\n\t\tif (this.plugins.has(plugin.name)) {\n\t\t\tthrow new Error(`Plugin \"${plugin.name}\" is already registered`)\n\t\t}\n\n\t\tthis.plugins.set(plugin.name, plugin)\n\t}\n\n\t/**\n\t * Unregisters a plugin from the registry\n\t *\n\t * @param name - The name of the plugin to unregister\n\t * @returns True if the plugin was unregistered, false if it wasn't found\n\t */\n\tunregister(name: string): boolean {\n\t\treturn this.plugins.delete(name)\n\t}\n\n\t/**\n\t * Gets a plugin by name\n\t *\n\t * @param name - The name of the plugin to retrieve\n\t * @returns The plugin if found, undefined otherwise\n\t */\n\tget(name: string): Plugin<T> | undefined {\n\t\treturn this.plugins.get(name)\n\t}\n\n\t/**\n\t * Gets all registered plugins\n\t *\n\t * @returns Array of all registered plugins\n\t */\n\tgetAll(): Plugin<T>[] {\n\t\treturn Array.from(this.plugins.values())\n\t}\n\n\t/**\n\t * Checks if a plugin is registered\n\t *\n\t * @param name - The name of the plugin to check\n\t * @returns True if the plugin is registered, false otherwise\n\t */\n\thas(name: string): boolean {\n\t\treturn this.plugins.has(name)\n\t}\n\n\t/**\n\t * Applies all registered plugins to a Hono app\n\t *\n\t * @param app - The Hono app instance to extend\n\t * @param context - Optional context data passed to all plugins\n\t */\n\tasync applyAll(\n\t\tapp: Hono<{ Variables: HonoVariables }>,\n\t\tcontext?: T\n\t): Promise<void> {\n\t\tconst plugins = this.getAll()\n\n\t\tfor (const plugin of plugins) {\n\t\t\ttry {\n\t\t\t\tconsole.log(`🔌 Applying plugin: ${plugin.name}`)\n\t\t\t\tawait plugin.apply(app, context)\n\t\t\t\tconsole.log(`✅ Plugin applied: ${plugin.name}`)\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(`❌ Failed to apply plugin ${plugin.name}:`, error)\n\t\t\t\tthrow error\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Clears all registered plugins\n\t */\n\tclear(): void {\n\t\tthis.plugins.clear()\n\t}\n\n\t/**\n\t * Gets the number of registered plugins\n\t */\n\tget size(): number {\n\t\treturn this.plugins.size\n\t}\n}\n\n/**\n * Creates a plugin that mounts routes at a specific path\n *\n * @param name - Plugin name\n * @param path - Path to mount the routes at\n * @param routes - Hono app containing the routes to mount\n * @returns A plugin that mounts the routes\n */\nexport function createRoutePlugin(\n\tname: string,\n\tpath: string,\n\troutes: Hono<{ Variables: HonoVariables }>\n): Plugin {\n\treturn {\n\t\tname,\n\t\tdescription: `Mounts routes at ${path}`,\n\t\tapply: (app: Hono<{ Variables: HonoVariables }>) => {\n\t\t\tapp.route(path, routes)\n\t\t}\n\t}\n}\n\n/**\n * Creates a plugin that applies middleware\n *\n * @param name - Plugin name\n * @param middleware - Middleware function to apply\n * @returns A plugin that applies the middleware\n */\nexport function createMiddlewarePlugin(\n\tname: string,\n\tmiddleware: (app: Hono<{ Variables: HonoVariables }>) => void\n): Plugin {\n\treturn {\n\t\tname,\n\t\tdescription: `Applies middleware: ${name}`,\n\t\tapply: middleware\n\t}\n}\n","import { Tool as AISDKTool, type UIMessage } from \"ai\"\nimport { z } from \"zod\"\nimport { AgentRuntime } from \"../types\"\n\ntype DefaultRuntimeExtension = Record<string, never>\n\n/**\n * Configuration interface for creating custom tools that integrate with AI SDK.\n */\nexport interface ToolConfig<\n\tTInput extends z.ZodTypeAny = z.ZodTypeAny,\n\tTOutput extends z.ZodTypeAny = z.ZodTypeAny,\n\tTRuntimeExtension = DefaultRuntimeExtension\n> {\n\t/** Unique identifier for the tool */\n\tid: string\n\t/** Human-readable description of what the tool does */\n\tdescription: string\n\t/** Zod schema for validating tool input */\n\tinputSchema: TInput\n\t/** Optional Zod schema for validating tool output */\n\toutputSchema?: TOutput\n\t/** Function that executes the tool's logic */\n\texecute: (args: {\n\t\tinput: z.infer<TInput>\n\t\truntime: AgentRuntime & TRuntimeExtension\n\t\tmessages: UIMessage[]\n\t}) => Promise<z.infer<TOutput>>\n}\n\n/**\n * Internal tool interface used throughout the agent framework.\n * Similar to ToolConfig but without the ID field, used after tool creation.\n */\nexport interface Tool<\n\tTInput extends z.ZodTypeAny = z.ZodTypeAny,\n\tTOutput extends z.ZodTypeAny = z.ZodTypeAny,\n\tTRuntimeExtension = DefaultRuntimeExtension\n> {\n\t/** Human-readable description of what the tool does */\n\tdescription: string\n\t/** Zod schema for validating tool input */\n\tinputSchema: TInput\n\t/** Optional Zod schema for validating tool output */\n\toutputSchema?: TOutput\n\t/** Function that executes the tool's logic */\n\texecute: (args: {\n\t\tinput: z.infer<TInput>\n\t\truntime: AgentRuntime & TRuntimeExtension\n\t\tmessages: UIMessage[]\n\t}) => Promise<z.infer<TOutput>>\n}\n\n/**\n * Factory function to create tools with custom runtime extensions.\n * Provides proper type inference for input/output schemas and runtime extensions.\n */\nexport function toolFactory<TRuntimeExtension = DefaultRuntimeExtension>() {\n\treturn <\n\t\tTInput extends z.ZodTypeAny,\n\t\tTOutput extends z.ZodTypeAny = z.ZodTypeAny\n\t>(\n\t\tconfig: ToolConfig<TInput, TOutput, TRuntimeExtension>\n\t): Tool<TInput, TOutput, TRuntimeExtension> => {\n\t\treturn {\n\t\t\tdescription: config.description,\n\t\t\tinputSchema: config.inputSchema,\n\t\t\toutputSchema: config.outputSchema,\n\t\t\texecute: async (args) => {\n\t\t\t\tconst input = config.inputSchema.parse(args.input)\n\t\t\t\tconst result = await config.execute({\n\t\t\t\t\tinput,\n\t\t\t\t\truntime: args.runtime,\n\t\t\t\t\tmessages: args.messages\n\t\t\t\t})\n\t\t\t\tif (config.outputSchema) {\n\t\t\t\t\treturn config.outputSchema.parse(result)\n\t\t\t\t}\n\t\t\t\treturn result\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Default tool factory with no runtime extensions.\n * Type-safe at creation time with proper schema inference.\n */\nexport const createTool = toolFactory()\n\n/**\n * Converts a custom Tool instance to AI SDK's tool format.\n * This adapter enables our tools to work with AI SDK's generateText/streamText functions.\n */\nexport function toAISDKTool<\n\tTRuntimeExtension = DefaultRuntimeExtension,\n\tTInput extends z.ZodTypeAny = z.ZodTypeAny,\n\tTOutput extends z.ZodTypeAny = z.ZodTypeAny\n>(\n\ttool: Tool<TInput, TOutput, TRuntimeExtension>,\n\truntime: AgentRuntime & TRuntimeExtension,\n\tmessages: UIMessage[]\n): AISDKTool {\n\treturn {\n\t\tdescription: tool.description,\n\t\tinputSchema: tool.inputSchema,\n\t\texecute: async (args: z.infer<TInput>) => {\n\t\t\treturn tool.execute({\n\t\t\t\tinput: args,\n\t\t\t\truntime,\n\t\t\t\tmessages\n\t\t\t})\n\t\t}\n\t}\n}\n\n/**\n * Converts a collection of custom tools to AI SDK format.\n * Useful for batch conversion when setting up multiple tools for AI SDK usage.\n */\nexport function toAISDKTools<\n\tTRuntimeExtension = DefaultRuntimeExtension,\n\tTInput extends z.ZodTypeAny = z.ZodTypeAny,\n\tTOutput extends z.ZodTypeAny = z.ZodTypeAny\n>(\n\ttools: Record<string, Tool<TInput, TOutput, TRuntimeExtension>>,\n\truntime: AgentRuntime & TRuntimeExtension,\n\tmessages: UIMessage[]\n): Record<string, AISDKTool> {\n\tconst convertedTools: Record<string, AISDKTool> = {}\n\n\tfor (const [name, tool] of Object.entries(tools)) {\n\t\tconvertedTools[name] = toAISDKTool(tool, runtime, messages)\n\t}\n\n\treturn convertedTools\n}\n"],"mappings":"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","names":["randomUUID","randomUUID"]}
1
+ {"version":3,"sources":["../src/core/agent.ts","../src/lib/render.ts","../src/server/listen.ts","../src/xmtp/plugin.ts","../src/server/processor.ts","../src/lib/jwt.ts","../src/core/plugin.ts","../src/core/tool.ts","../src/tools/blockchain.ts","../src/tools/xmtp.ts"],"sourcesContent":["import { randomUUID } from \"@hybrd/utils\"\nimport {\n\tLanguageModel,\n\tTelemetrySettings,\n\tUIMessage,\n\tUIMessageStreamOnFinishCallback,\n\tconvertToModelMessages,\n\tgenerateText,\n\tsmoothStream,\n\tstepCountIs,\n\tstreamText\n} from \"ai\"\nimport { z } from \"zod\"\nimport { render } from \"../lib/render\"\nimport type { PluginContext } from \"../server/listen\"\nimport { ListenOptions, listen } from \"../server/listen\"\nimport type { AgentRuntime } from \"../types\"\nimport type { Plugin } from \"./plugin\"\nimport { PluginRegistry } from \"./plugin\"\nimport { Tool, toAISDKTools } from \"./tool\"\n\nexport type DefaultRuntimeExtension = Record<string, never>\n\n/**\n * Tool that can be used in Agent configuration.\n * Extends the base Tool type with runtime extension support.\n */\ntype AgentTool<TRuntimeExtension = DefaultRuntimeExtension> = Tool<\n\tz.ZodTypeAny,\n\tz.ZodTypeAny,\n\tTRuntimeExtension\n>\n\n/**\n * Function that generates tools dynamically based on messages and runtime context.\n * Allows for context-aware tool selection and configuration.\n */\nexport type ToolGenerator<TRuntimeExtension = DefaultRuntimeExtension> =\n\t(props: {\n\t\tmessages: UIMessage[]\n\t\truntime: AgentRuntime & TRuntimeExtension\n\t}) =>\n\t\t| Record<string, AgentTool<TRuntimeExtension>>\n\t\t| Promise<Record<string, AgentTool<TRuntimeExtension>>>\n\n/**\n * Configuration interface for creating an Agent instance.\n * Supports both static and dynamic configuration through functions.\n */\nexport interface AgentConfig<TRuntimeExtension = DefaultRuntimeExtension> {\n\t/** Unique identifier for the agent */\n\tname: string\n\t/** Language model to use, can be static or dynamically resolved */\n\tmodel:\n\t\t| LanguageModel\n\t\t| ((props: {\n\t\t\t\truntime: AgentRuntime & TRuntimeExtension\n\t\t }) => LanguageModel | Promise<LanguageModel>)\n\t/** Tools available to the agent, can be static or dynamically generated */\n\ttools?:\n\t\t| Record<string, AgentTool<TRuntimeExtension>>\n\t\t| ToolGenerator<TRuntimeExtension>\n\t/** Instructions for the agent, can be static or dynamically resolved */\n\tinstructions:\n\t\t| string\n\t\t| ((props: {\n\t\t\t\tmessages: UIMessage[]\n\t\t\t\truntime: AgentRuntime & TRuntimeExtension\n\t\t }) => string | Promise<string>)\n\t/** Function to create the runtime extension, type will be inferred */\n\tcreateRuntime?: (\n\t\truntime: AgentRuntime\n\t) => TRuntimeExtension | Promise<TRuntimeExtension>\n\t/** Optional metadata for the agent */\n\tmetadata?: Record<string, unknown>\n\t/** Maximum number of steps the agent can take */\n\tmaxSteps?: number\n\t/** Maximum tokens for generation */\n\tmaxTokens?: number\n\t/** Temperature for generation (0.0 to 2.0) */\n\ttemperature?: number\n}\n\n/**\n * Options for text generation with the agent.\n * Extends AI SDK parameters while adding agent-specific options.\n */\nexport interface GenerateOptions<TRuntimeExtension = DefaultRuntimeExtension>\n\textends Omit<\n\t\tParameters<typeof generateText>[0],\n\t\t\"model\" | \"tools\" | \"instructions\" | \"onFinish\"\n\t> {\n\t/** Maximum tokens for generation */\n\tmaxTokens?: number\n\t/** Runtime context for the agent */\n\truntime: AgentRuntime & TRuntimeExtension\n\t/** Optional telemetry configuration */\n\ttelemetry?: NonNullable<TelemetrySettings>\n}\n\n/**\n * Options for streaming text with the agent.\n * Extends AI SDK parameters while adding agent-specific options.\n */\nexport interface StreamOptions<TRuntimeExtension = DefaultRuntimeExtension>\n\textends Omit<\n\t\tParameters<typeof streamText>[0],\n\t\t\"model\" | \"tools\" | \"instructions\" | \"onFinish\"\n\t> {\n\t/** Maximum tokens for generation */\n\tmaxTokens?: number\n\t/** Runtime context for the agent */\n\truntime: AgentRuntime & TRuntimeExtension\n\t/** Optional telemetry configuration */\n\ttelemetry?: NonNullable<TelemetrySettings>\n\t/** Callback when streaming finishes */\n\tonFinish?: UIMessageStreamOnFinishCallback<UIMessage>\n}\n\n/**\n * Core Agent implementation using AI SDK 5 directly.\n * This class provides a flexible interface for creating AI agents with\n * dynamic configuration, tool support, and streaming capabilities.\n */\nexport class Agent<TRuntimeExtension = DefaultRuntimeExtension> {\n\t/** Agent's unique identifier */\n\tpublic readonly name: string\n\t/** Optional description of the agent */\n\tpublic readonly description?: string\n\t/** Optional metadata associated with the agent */\n\tpublic readonly metadata?: Record<string, unknown>\n\t/** Agent configuration */\n\tprivate readonly config: AgentConfig<TRuntimeExtension>\n\t/** Default parameters for text generation */\n\tprivate readonly generationDefaults: Partial<\n\t\tPick<\n\t\t\tParameters<typeof generateText>[0],\n\t\t\t| \"model\"\n\t\t\t| \"messages\"\n\t\t\t| \"tools\"\n\t\t\t| \"toolChoice\"\n\t\t\t| \"stopWhen\"\n\t\t\t| \"maxOutputTokens\"\n\t\t\t| \"temperature\"\n\t\t>\n\t>\n\t/** Default parameters for text streaming */\n\tprivate readonly streamDefaults: Partial<\n\t\tPick<\n\t\t\tParameters<typeof streamText>[0],\n\t\t\t| \"model\"\n\t\t\t| \"messages\"\n\t\t\t| \"tools\"\n\t\t\t| \"toolChoice\"\n\t\t\t| \"stopWhen\"\n\t\t\t| \"experimental_transform\"\n\t\t\t| \"maxOutputTokens\"\n\t\t\t| \"temperature\"\n\t\t>\n\t>\n\t/** Plugin registry for extending the agent's HTTP server */\n\tpublic readonly plugins: PluginRegistry<PluginContext>\n\n\t/**\n\t * Creates a new Agent instance with the specified configuration.\n\t * @param config - Configuration object for the agent\n\t */\n\tconstructor(config: AgentConfig<TRuntimeExtension>) {\n\t\tthis.name = config.name\n\t\tthis.metadata = config.metadata\n\t\tthis.config = config\n\t\tthis.plugins = new PluginRegistry<PluginContext>()\n\n\t\tthis.generationDefaults = {\n\t\t\tmaxOutputTokens: config.maxTokens,\n\t\t\ttemperature: config.temperature\n\t\t}\n\n\t\tthis.streamDefaults = {\n\t\t\tmaxOutputTokens: config.maxTokens,\n\t\t\ttemperature: config.temperature\n\t\t}\n\t}\n\n\t/**\n\t * Resolves dynamic configuration properties (model, tools, instructions) with runtime context.\n\t * @param messages - Current conversation messages\n\t * @param runtime - Runtime context for the agent\n\t * @returns Resolved configuration with model, tools, and instructions\n\t */\n\tprivate async resolveConfig(\n\t\tmessages: UIMessage[],\n\t\truntime: AgentRuntime & TRuntimeExtension\n\t): Promise<{\n\t\tmodel: LanguageModel\n\t\ttools?: Record<string, Tool<z.ZodTypeAny, z.ZodTypeAny, TRuntimeExtension>>\n\t\tinstructions?: string\n\t}> {\n\t\tconst props = { messages, runtime }\n\n\t\tconst model =\n\t\t\ttypeof this.config.model === \"function\"\n\t\t\t\t? await this.config.model(props)\n\t\t\t\t: this.config.model\n\n\t\tconst tools =\n\t\t\ttypeof this.config.tools === \"function\"\n\t\t\t\t? await this.config.tools(props)\n\t\t\t\t: this.config.tools\n\n\t\tconst instructions =\n\t\t\ttypeof this.config.instructions === \"function\"\n\t\t\t\t? await this.config.instructions(props)\n\t\t\t\t: this.config.instructions\n\n\t\treturn {\n\t\t\tmodel,\n\t\t\ttools,\n\t\t\tinstructions: render(instructions, runtime)\n\t\t}\n\t}\n\n\t/**\n\t * Prepares messages by adding system instructions if provided.\n\t * Merges instructions with existing system messages or creates new ones.\n\t * @param messages - Current conversation messages\n\t * @param instructions - System instructions to add\n\t * @returns Messages with system instructions properly integrated\n\t */\n\tprivate prepareMessages(\n\t\tmessages: UIMessage[],\n\t\tinstructions?: string\n\t): UIMessage[] {\n\t\tif (!instructions) {\n\t\t\treturn messages\n\t\t}\n\n\t\tif (messages[0]?.role === \"system\") {\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\t...messages[0],\n\t\t\t\t\tparts: [{ type: \"text\", text: instructions }]\n\t\t\t\t},\n\t\t\t\t...messages.slice(1)\n\t\t\t]\n\t\t}\n\n\t\treturn [\n\t\t\t{\n\t\t\t\trole: \"system\",\n\t\t\t\tid: randomUUID(),\n\t\t\t\tparts: [{ type: \"text\", text: instructions }]\n\t\t\t},\n\t\t\t...messages\n\t\t]\n\t}\n\n\t/**\n\t * Generates a text completion using the agent's configuration.\n\t * @param messages - Conversation messages to generate from\n\t * @param options - Generation options including runtime context\n\t * @returns Generated text completion result\n\t */\n\tasync generate(\n\t\tmessages: UIMessage[],\n\t\toptions: GenerateOptions<TRuntimeExtension>\n\t) {\n\t\t// Ensure runtime is properly extended with createRuntime function\n\t\tconst extendedRuntime = await this.createRuntimeContext(options.runtime)\n\n\t\tconst { model, tools, instructions } = await this.resolveConfig(\n\t\t\tmessages,\n\t\t\textendedRuntime\n\t\t)\n\n\t\tconst preparedMessages = this.prepareMessages(messages, instructions)\n\n\t\tconst { runtime, maxTokens, telemetry, prompt, ...aiSdkOptions } = options\n\n\t\tconst aiSDKTools = tools\n\t\t\t? toAISDKTools<TRuntimeExtension, z.ZodTypeAny, z.ZodTypeAny>(\n\t\t\t\t\ttools,\n\t\t\t\t\textendedRuntime,\n\t\t\t\t\tpreparedMessages\n\t\t\t\t)\n\t\t\t: undefined\n\n\t\tconst result = await generateText({\n\t\t\t...this.generationDefaults,\n\t\t\t...aiSdkOptions,\n\t\t\tmodel,\n\t\t\tmessages: convertToModelMessages(preparedMessages),\n\t\t\ttools: aiSDKTools,\n\t\t\ttoolChoice:\n\t\t\t\taiSDKTools && Object.keys(aiSDKTools).length > 0 ? \"auto\" : undefined,\n\t\t\tstopWhen: [stepCountIs(this.config.maxSteps ?? 5)],\n\t\t\tmaxOutputTokens: maxTokens\n\t\t})\n\n\t\treturn result\n\t}\n\n\t/**\n\t * Streams a text completion using the agent's configuration.\n\t * @param messages - Conversation messages to generate from\n\t * @param options - Streaming options including runtime context\n\t * @returns Streaming response that can be consumed\n\t */\n\tasync stream(\n\t\tmessages: UIMessage[],\n\t\toptions: StreamOptions<TRuntimeExtension>\n\t) {\n\t\t// Ensure runtime is properly extended with createRuntime function\n\t\tconst extendedRuntime = await this.createRuntimeContext(options.runtime)\n\n\t\tconst { model, tools, instructions } = await this.resolveConfig(\n\t\t\tmessages,\n\t\t\textendedRuntime\n\t\t)\n\n\t\tconst preparedMessages = this.prepareMessages(messages, instructions)\n\n\t\tconst { runtime, onFinish, maxTokens, telemetry, prompt, ...aiSdkOptions } =\n\t\t\toptions\n\n\t\tconst aiSDKTools = tools\n\t\t\t? toAISDKTools<TRuntimeExtension, z.ZodTypeAny, z.ZodTypeAny>(\n\t\t\t\t\ttools,\n\t\t\t\t\textendedRuntime,\n\t\t\t\t\tpreparedMessages\n\t\t\t\t)\n\t\t\t: undefined\n\n\t\tconst result = await streamText({\n\t\t\t...this.streamDefaults,\n\t\t\t...aiSdkOptions,\n\t\t\tmodel,\n\t\t\tmessages: convertToModelMessages(preparedMessages),\n\t\t\ttools: aiSDKTools,\n\t\t\ttoolChoice:\n\t\t\t\taiSDKTools && Object.keys(aiSDKTools).length > 0 ? \"auto\" : undefined,\n\t\t\tstopWhen: [stepCountIs(this.config.maxSteps ?? 5)],\n\t\t\texperimental_transform: smoothStream(),\n\t\t\tmaxOutputTokens: maxTokens\n\t\t})\n\n\t\treturn result.toUIMessageStreamResponse({\n\t\t\toriginalMessages: messages,\n\t\t\tonFinish\n\t\t})\n\t}\n\n\t/**\n\t * Gets the agent's configuration for debugging and inspection.\n\t * @returns Object containing agent configuration details\n\t */\n\tgetConfig() {\n\t\treturn {\n\t\t\tname: this.name,\n\t\t\tdescription: this.description,\n\t\t\tmetadata: this.metadata,\n\t\t\thasModel: !!this.config.model,\n\t\t\thasTools: !!this.config.tools,\n\t\t\thasInstructions: !!this.config.instructions\n\t\t}\n\t}\n\n\t/**\n\t * Gets the agent's instructions without running generation.\n\t * Useful for external integrations that need instructions separately.\n\t * @param options - Options containing runtime context and optional messages\n\t * @returns Resolved instructions string\n\t */\n\tasync getInstructions(options: {\n\t\truntime: AgentRuntime & TRuntimeExtension\n\t\tmessages?: UIMessage[]\n\t}) {\n\t\t// Ensure runtime is properly extended with createRuntime function\n\t\tconst extendedRuntime = await this.createRuntimeContext(options.runtime)\n\n\t\tconst messages = options.messages || []\n\t\tconst props = { messages, runtime: extendedRuntime }\n\n\t\tif (typeof this.config.instructions === \"function\") {\n\t\t\treturn await this.config.instructions(props)\n\t\t}\n\t\treturn this.config.instructions\n\t}\n\n\t/**\n\t * Gets the agent's tools without running generation.\n\t * Useful for external integrations that need tools separately.\n\t * @param options - Options containing runtime context and optional messages\n\t * @returns Resolved tools object\n\t */\n\tasync getTools(options: {\n\t\truntime: AgentRuntime & TRuntimeExtension\n\t\tmessages?: UIMessage[]\n\t}) {\n\t\t// Ensure runtime is properly extended with createRuntime function\n\t\tconst extendedRuntime = await this.createRuntimeContext(options.runtime)\n\n\t\tconst messages = options.messages || []\n\t\tconst props = { messages, runtime: extendedRuntime }\n\n\t\tif (typeof this.config.tools === \"function\") {\n\t\t\treturn await this.config.tools(props)\n\t\t}\n\t\treturn this.config.tools\n\t}\n\n\t/**\n\t * Creates the complete runtime context by merging base runtime with custom extension.\n\t * @param baseRuntime - The base runtime context containing XMTP properties\n\t * @returns Complete runtime context with custom extensions applied\n\t */\n\t/**\n\t * Creates the complete runtime context by merging base runtime with custom extension.\n\t * @param baseRuntime - The base runtime context containing XMTP properties\n\t * @returns Complete runtime context with custom extensions applied\n\t */\n\tasync createRuntimeContext(\n\t\tbaseRuntime: AgentRuntime\n\t): Promise<AgentRuntime & TRuntimeExtension> {\n\t\t// Always start with the default runtime (baseRuntime)\n\t\tlet completeRuntime = { ...baseRuntime } as AgentRuntime & TRuntimeExtension\n\n\t\t// If user provided createRuntime function, extend the default runtime\n\t\tif (this.config.createRuntime) {\n\t\t\tconst userExtension = await this.config.createRuntime(completeRuntime)\n\t\t\tcompleteRuntime = {\n\t\t\t\t...completeRuntime,\n\t\t\t\t...userExtension\n\t\t\t} as AgentRuntime & TRuntimeExtension\n\t\t}\n\n\t\treturn completeRuntime\n\t}\n\n\t/**\n\t * Registers a plugin with the agent\n\t *\n\t * @param plugin - The plugin to register\n\t */\n\tuse(plugin: Plugin<PluginContext>): void {\n\t\tthis.plugins.register(plugin)\n\t}\n\n\t/**\n\t * Starts listening for messages and events using the agent instance.\n\t * @param opts - Configuration options for the listener, excluding the agent property\n\t */\n\tasync listen(opts: Omit<ListenOptions, \"agent\">) {\n\t\tlisten({ ...opts, agent: this as Agent<DefaultRuntimeExtension> })\n\t}\n}\n","import { Eta } from \"eta\"\n\nexport const eta = new Eta({\n\tviews: \"templates\"\n})\n\nexport const render = (template: string, runtime: Record<string, unknown>) => {\n\treturn eta.renderString(template, runtime)\n}\n","import { serve } from \"@hono/node-server\"\nimport { getCloudflareStoragePath } from \"@hybrd/utils\"\nimport type { MessageListenerConfig, XmtpClient } from \"@hybrd/xmtp\"\nimport { type HonoVariables, createXMTPClient } from \"@hybrd/xmtp\"\nimport { Context, Hono, Next } from \"hono\"\nimport type { Agent, DefaultRuntimeExtension } from \"../core/agent\"\nimport type { Plugin } from \"../core/plugin\"\nimport { XMTPPlugin } from \"../xmtp/plugin\"\nimport {\n\tcreateBackgroundMessageProcessor,\n\tgetBgState,\n\tstopBackground\n} from \"./processor\"\n\nexport type { HonoVariables } from \"@hybrd/xmtp\"\n\n/**\n * Creates Hono middleware to inject XMTP client into request context\n *\n * @description\n * This middleware function sets the XMTP client instance in the Hono context,\n * making it available to all subsequent middleware and route handlers.\n * The client can be accessed via `c.get(\"xmtpClient\")` in route handlers.\n *\n * @param client - The XMTP client instance to inject into the context\n * @returns Hono middleware function that sets the XMTP client in context\n *\n * @example\n * ```typescript\n * app.use(createHonoMiddleware(xmtpClient))\n *\n * app.get(\"/messages\", (c) => {\n * const client = c.get(\"xmtpClient\")\n * // Use the client to interact with XMTP\n * })\n * ```\n */\nexport function createHonoMiddleware(client: XmtpClient) {\n\treturn async (c: Context, next: Next) => {\n\t\tc.set(\"xmtpClient\", client)\n\t\treturn next()\n\t}\n}\n\n/**\n * Options for creating a Hono app with XMTP integration\n *\n * @description\n * Configuration object for setting up a Hono application that includes\n * XMTP client middleware, background message processing, and XMTP tools routes.\n *\n * @template TRuntimeExtension - Runtime extension type for the agent\n * @property agent - The agent instance to use for message processing\n */\nexport type CreateHonoAppOptions<TRuntimeExtension = DefaultRuntimeExtension> =\n\t{\n\t\tagent: Agent<TRuntimeExtension>\n\t\tmessageFilter: MessageListenerConfig[\"filter\"]\n\t}\n\n/**\n * Creates a Hono app with full XMTP integration and background message processing\n *\n * @description\n * This function creates a complete Hono application configured with:\n * - XMTP client middleware for request context\n * - Background message processor for handling XMTP messages\n * - XMTP tools routes for external integrations\n * - Environment variable validation for required XMTP credentials\n *\n * The app automatically starts a background message processor that listens for\n * XMTP messages and forwards them to the provided agent for processing.\n *\n * @template TRuntimeExtension - Runtime extension type for the agent\n * @param options - Configuration options for the Hono app\n * @param options.agent - The agent instance to handle XMTP messages\n * @returns Promise that resolves to a configured Hono app instance\n *\n * @throws {Error} When XMTP_WALLET_KEY environment variable is not set\n * @throws {Error} When XMTP_ENCRYPTION_KEY environment variable is not set\n *\n * @example\n * ```typescript\n * const app = await createHonoApp({ agent: myAgent })\n *\n * // The app now has XMTP integration and background processing\n * app.get(\"/health\", (c) => c.json({ status: \"ok\" }))\n * ```\n */\nexport async function createHonoApp<\n\tTRuntimeExtension = DefaultRuntimeExtension\n>({ agent, messageFilter }: CreateHonoAppOptions<TRuntimeExtension>) {\n\tconst app = new Hono<{ Variables: HonoVariables }>()\n\n\tconst { XMTP_WALLET_KEY, XMTP_ENCRYPTION_KEY, XMTP_ENV } = process.env\n\n\tif (!XMTP_WALLET_KEY) {\n\t\tthrow new Error(\"XMTP_WALLET_KEY must be set\")\n\t}\n\n\tif (!XMTP_ENCRYPTION_KEY) {\n\t\tthrow new Error(\"XMTP_ENCRYPTION_KEY must be set\")\n\t}\n\n\t// Create xmtpClient with persistent storage for reliable message streaming\n\tconst cloudflareStoragePath = getCloudflareStoragePath(\"xmtp\")\n\tconst xmtpClient = await createXMTPClient(XMTP_WALLET_KEY as string, {\n\t\tpersist: true,\n\t\tstoragePath: cloudflareStoragePath\n\t})\n\n\t// Apply middleware for XMTP client\n\tapp.use(createHonoMiddleware(xmtpClient))\n\n\t// Start the background message processor\n\tapp.use(\n\t\tcreateBackgroundMessageProcessor({\n\t\t\tagent,\n\t\t\txmtpClient,\n\t\t\tmessageFilter, // Accept all messages by default\n\t\t\tintervalMs: 5_000, // Check every 5 seconds\n\t\t\tbackoffMs: 1_000, // Start with 1 second backoff\n\t\t\tmaxBackoffMs: 30_000 // Max 30 seconds backoff\n\t\t})\n\t)\n\n\t// Mount XMTP tools routes\n\t// app.route(\"/xmtp-tools\", xmtpApp) // This line is removed as per the edit hint\n\n\treturn app\n}\n\n/**\n * Context type for plugins that need agent information\n */\nexport interface PluginContext {\n\tagent: Agent<DefaultRuntimeExtension>\n}\n\n/**\n * Options for starting the XMTP tools HTTP server\n *\n * @description\n * Configuration object for the standalone XMTP tools server that provides\n * basic HTTP endpoints for health checks and XMTP operations.\n *\n * @property agent - The agent instance to associate with the server\n * @property port - The port number to listen on (defaults to 8454)\n * @property filter - Optional message filter for XMTP messages\n * @property plugins - Optional array of plugins to apply to the server\n */\nexport type ListenOptions = {\n\tagent: Agent\n\tport: string\n\tfilter?: MessageListenerConfig[\"filter\"]\n\tplugins?: Plugin<PluginContext>[]\n}\n\n/**\n * Starts a standalone XMTP tools HTTP server\n *\n * @description\n * This function creates and starts a minimal HTTP server specifically for\n * XMTP tools operations. It includes:\n * - Health check endpoint at `/health`\n * - 404 handler for unmatched routes\n * - Automatic port parsing from string input\n * - Plugin-based route mounting\n *\n * The server runs independently and is useful for scenarios where you need\n * XMTP tools functionality without the full Hono app integration.\n *\n * @param options - Configuration options for the server\n * @param options.agent - The agent instance to associate with the server\n * @param options.port - The port number to listen on (parsed as integer)\n *\n * @example\n * ```typescript\n * listen({\n * agent: myAgent,\n * port: \"3000\"\n * })\n *\n * // Server starts on port 3000 with health endpoint at /health\n * // and all registered plugins applied\n * ```\n */\nexport async function listen({\n\tagent,\n\tport,\n\tfilter,\n\tplugins = []\n}: ListenOptions) {\n\tconst app = new Hono<{ Variables: HonoVariables }>()\n\tconst context: PluginContext = {\n\t\tagent\n\t}\n\n\tconst xmtpPlugin = XMTPPlugin({\n\t\tfilter\n\t})\n\n\t// Right now we always apply the XMTP plugin, but this may change in the future.\n\tawait xmtpPlugin.apply(app, context)\n\n\t// Apply plugins from agent registry first\n\tawait agent.plugins.applyAll(app, context)\n\n\t// Apply plugins from listen options\n\tfor (const plugin of plugins) {\n\t\ttry {\n\t\t\tconsole.log(`🔌 Applying plugin: ${plugin.name}`)\n\t\t\tawait plugin.apply(app, context)\n\t\t\tconsole.log(`✅ Plugin applied: ${plugin.name}`)\n\t\t} catch (error) {\n\t\t\tconsole.error(`❌ Failed to apply plugin ${plugin.name}:`, error)\n\t\t\tthrow error\n\t\t}\n\t}\n\n\tapp.get(\"/health\", (c) => {\n\t\treturn c.json({\n\t\t\tstatus: \"healthy\",\n\t\t\tservice: agent.name,\n\t\t\ttimestamp: new Date().toISOString()\n\t\t})\n\t})\n\n\tapp.notFound((c) => {\n\t\treturn c.json({ error: \"Not found\" }, 404)\n\t})\n\n\tserve({\n\t\tfetch: app.fetch,\n\t\tport: Number.parseInt(port || \"8454\")\n\t})\n\n\tconsole.log(`✅ XMTP Tools HTTP Server running`)\n}\n\n// Re-export the background processor helpers\nexport { getBgState, stopBackground }\n","import { MessageListenerConfig } from \"@hybrd/xmtp\"\nimport type { Agent, DefaultRuntimeExtension } from \"../core/agent\"\nimport type { Plugin } from \"../core/plugin\"\nimport { createHonoApp } from \"../server/listen\"\n\n/**\n * Context for the XMTP plugin\n */\nexport interface XMTPPluginContext {\n\tagent: Agent<DefaultRuntimeExtension>\n}\n\n/**\n * XMTP Plugin that provides XMTP functionality to the agent\n *\n * @description\n * This plugin integrates XMTP messaging capabilities into the agent's\n * HTTP server. It creates a Hono app with XMTP client middleware,\n * background message processing, and XMTP tools routes.\n *\n * Note: This plugin requires the agent to be configured with XMTP\n * environment variables and the listen method to be called with a filter.\n */\nexport function XMTPPlugin({\n\tfilter\n}: {\n\tfilter: MessageListenerConfig[\"filter\"]\n}): Plugin<XMTPPluginContext> {\n\treturn {\n\t\tname: \"xmtp\",\n\t\tdescription: \"Provides XMTP messaging functionality\",\n\t\tapply: async (app, context) => {\n\t\t\tif (!context) {\n\t\t\t\tthrow new Error(\"XMTP plugin requires context with agent\")\n\t\t\t}\n\n\t\t\tconst { agent } = context\n\n\t\t\t// Create the XMTP Hono app with a default filter that accepts all messages\n\t\t\t// The actual filter will be applied when the listen method is called\n\t\t\tconst xmtpApp = await createHonoApp({\n\t\t\t\tagent,\n\t\t\t\tmessageFilter: filter\n\t\t\t})\n\n\t\t\t// Mount the XMTP app at the root\n\t\t\tapp.route(\"/\", xmtpApp)\n\t\t}\n\t}\n}\n","import {\n\tMessageEvent,\n\tMessageListener,\n\tMessageListenerConfig,\n\tXmtpClient,\n\tcreateAuthenticatedXmtpClient\n} from \"@hybrd/xmtp\"\nimport { type MiddlewareHandler } from \"hono\"\nimport { randomUUID } from \"node:crypto\"\nimport { createPublicClient, http } from \"viem\"\nimport { base } from \"viem/chains\"\nimport type { Agent } from \"../core/agent\"\nimport { generateXMTPToolsToken } from \"../lib/jwt\"\nimport type { AgentRuntime } from \"../types\"\n\n// Global state management\nconst BG_STARTED = Symbol(\"BG_STARTED\")\nconst BG_STATE = Symbol(\"BG_STATE\")\nconst BG_STOP = Symbol(\"BG_STOP\")\n\ninterface BgState {\n\trunning: boolean\n\tlastStartAt: number\n\tlastOkAt?: number\n\tlastErrAt?: number\n\tconsecutiveErrors: number\n\tmessagesProcessed: number\n\tlistenerRunning: boolean\n}\n\ninterface BackgroundMessageProcessorOptions<\n\tTRuntimeExtension = Record<string, never>\n> {\n\tagent: Agent<TRuntimeExtension>\n\txmtpClient: XmtpClient\n\tmessageFilter: MessageListenerConfig[\"filter\"]\n\tintervalMs?: number\n\tbackoffMs?: number\n\tmaxBackoffMs?: number\n}\n\nfunction sleep(ms: number) {\n\treturn new Promise((r) => setTimeout(r, ms))\n}\n\nexport function createBackgroundMessageProcessor<\n\tTRuntimeExtension = Record<string, never>\n>(\n\topts: BackgroundMessageProcessorOptions<TRuntimeExtension>\n): MiddlewareHandler {\n\tif (!opts?.agent || !opts?.xmtpClient) {\n\t\tthrow new Error(\n\t\t\t\"createBackgroundMessageProcessor: agent and xmtpClient are required\"\n\t\t)\n\t}\n\n\tconst intervalMs = Math.max(250, opts.intervalMs ?? 5_000) // Check every 5 seconds by default\n\tconst baseBackoffMs = Math.max(100, opts.backoffMs ?? 1_000)\n\tconst maxBackoffMs = Math.max(baseBackoffMs, opts.maxBackoffMs ?? 30_000)\n\n\t// Ensure singleton in this process\n\tif (!(globalThis as any)[BG_STARTED]) {\n\t\t;(globalThis as any)[BG_STARTED] = true\n\n\t\tconst state: BgState = {\n\t\t\trunning: true,\n\t\t\tlastStartAt: Date.now(),\n\t\t\tconsecutiveErrors: 0,\n\t\t\tmessagesProcessed: 0,\n\t\t\tlistenerRunning: false\n\t\t}\n\t\t;(globalThis as any)[BG_STATE] = state\n\n\t\tconst ac = new AbortController()\n\t\tconst signal = ac.signal\n\n\t\tconst stop = () => {\n\t\t\tif (!state.running) return\n\t\t\tstate.running = false\n\t\t\tac.abort()\n\t\t\tconsole.log(\"[XMTP Background] Stopping message processor...\")\n\t\t}\n\t\t;(globalThis as any)[BG_STOP] = stop\n\n\t\tprocess.once(\"SIGINT\", stop)\n\t\tprocess.once(\"SIGTERM\", stop)\n\n\t\t// Create public client for address resolution\n\t\tconst publicClient = createPublicClient({\n\t\t\tchain: base,\n\t\t\ttransport: http()\n\t\t})\n\n\t\t// Create message listener - use type assertion to work around viem version differences\n\t\tconst listener = new MessageListener({\n\t\t\tpublicClient: publicClient as any,\n\t\t\txmtpClient: opts.xmtpClient,\n\t\t\tfilter: opts.messageFilter,\n\t\t\theartbeatInterval: 5 * 60 * 1000, // 5 minutes\n\t\t\tconversationCheckInterval: 30 * 1000 // 30 seconds\n\t\t})\n\n\t\t// Set up message event handler\n\t\tlistener.on(\"message\", async (messageEvent: MessageEvent) => {\n\t\t\ttry {\n\t\t\t\tconsole.log(\n\t\t\t\t\t`[XMTP Background] Processing message: ${messageEvent.message.content}`\n\t\t\t\t)\n\t\t\t\tconsole.log(\n\t\t\t\t\t`[XMTP Background] Sender: ${messageEvent.sender?.address || \"unknown\"}`\n\t\t\t\t)\n\t\t\t\tconsole.log(\n\t\t\t\t\t`[XMTP Background] Conversation: ${messageEvent.message.conversationId}`\n\t\t\t\t)\n\n\t\t\t\t// Create a simple message for the agent\n\t\t\t\tconst messages = [\n\t\t\t\t\t{\n\t\t\t\t\t\tid: randomUUID(),\n\t\t\t\t\t\trole: \"user\" as const,\n\t\t\t\t\t\tparts: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttype: \"text\" as const,\n\t\t\t\t\t\t\t\ttext: messageEvent.message.content?.toString() || \"\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t]\n\t\t\t\t\t}\n\t\t\t\t]\n\n\t\t\t\t// Create service client for agent runtime\n\t\t\t\tconst serviceUrl = process.env.AGENT_URL || \"http://localhost:8454\"\n\t\t\t\tconst serviceToken = generateXMTPToolsToken({\n\t\t\t\t\taction: \"send\",\n\t\t\t\t\tconversationId: messageEvent.message.conversationId,\n\t\t\t\t\tcontent: messageEvent.message.content?.toString() || \"\"\n\t\t\t\t})\n\t\t\t\tconst serviceClient = createAuthenticatedXmtpClient(\n\t\t\t\t\tserviceUrl,\n\t\t\t\t\tserviceToken\n\t\t\t\t)\n\n\t\t\t\t// Create base runtime context\n\t\t\t\tconst baseRuntime: AgentRuntime = {\n\t\t\t\t\tchatId: messageEvent.message.conversationId,\n\t\t\t\t\tmessages: messages,\n\t\t\t\t\tconversation: messageEvent.conversation,\n\t\t\t\t\tmessage: messageEvent.message,\n\t\t\t\t\tparentMessage: messageEvent.parentMessage,\n\t\t\t\t\trootMessage: messageEvent.rootMessage,\n\t\t\t\t\tsender: messageEvent.sender,\n\t\t\t\t\tsubjects: messageEvent.subjects,\n\t\t\t\t\txmtpClient: serviceClient\n\t\t\t\t}\n\n\t\t\t\t// Create complete runtime context using agent's createRuntime function\n\t\t\t\tconst runtime = await opts.agent.createRuntimeContext(baseRuntime)\n\n\t\t\t\t// Call the agent to process the message\n\t\t\t\tconsole.log(\"[XMTP Background] Calling agent to process message...\")\n\t\t\t\tconst result = await opts.agent.generate(messages, { runtime })\n\n\t\t\t\tif (result.text) {\n\t\t\t\t\t// Send the response back to the conversation\n\t\t\t\t\tawait messageEvent.conversation.send(result.text)\n\t\t\t\t\tconsole.log(`[XMTP Background] Agent response sent: ${result.text}`)\n\t\t\t\t}\n\n\t\t\t\tstate.messagesProcessed++\n\t\t\t\tstate.lastOkAt = Date.now()\n\t\t\t\tstate.consecutiveErrors = 0\n\n\t\t\t\tconsole.log(\n\t\t\t\t\t`[XMTP Background] Message processed successfully. Total: ${state.messagesProcessed}`\n\t\t\t\t)\n\t\t\t} catch (error) {\n\t\t\t\tstate.lastErrAt = Date.now()\n\t\t\t\tstate.consecutiveErrors++\n\t\t\t\tconsole.error(\"[XMTP Background] Error processing message:\", error)\n\n\t\t\t\t// Try to send an error response\n\t\t\t\ttry {\n\t\t\t\t\tawait messageEvent.conversation.send(\n\t\t\t\t\t\t\"Sorry, I encountered an error processing your message.\"\n\t\t\t\t\t)\n\t\t\t\t} catch (sendError) {\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t\"[XMTP Background] Failed to send error message:\",\n\t\t\t\t\t\tsendError\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\n\t\tlistener.on(\"error\", (error: Error) => {\n\t\t\tstate.lastErrAt = Date.now()\n\t\t\tstate.consecutiveErrors++\n\t\t\tconsole.error(\"[XMTP Background] Message listener error:\", error)\n\t\t})\n\n\t\tlistener.on(\"started\", () => {\n\t\t\tstate.listenerRunning = true\n\t\t\tconsole.log(\"[XMTP Background] Message listener started\")\n\t\t})\n\n\t\tlistener.on(\"stopped\", () => {\n\t\t\tstate.listenerRunning = false\n\t\t\tconsole.log(\"[XMTP Background] Message listener stopped\")\n\t\t})\n\n\t\tlistener.on(\"heartbeat\", (stats) => {\n\t\t\tconsole.log(\n\t\t\t\t`[XMTP Background] Heartbeat - Messages: ${stats.messageCount}, Conversations: ${stats.conversationCount}`\n\t\t\t)\n\t\t})\n\n\t\t// Background supervisor loop\n\t\t;(async function supervise() {\n\t\t\tlet nextDelay = intervalMs\n\n\t\t\twhile (state.running) {\n\t\t\t\ttry {\n\t\t\t\t\t// Start the listener if not already running\n\t\t\t\t\tif (!state.listenerRunning) {\n\t\t\t\t\t\tconsole.log(\"[XMTP Background] Starting message listener...\")\n\t\t\t\t\t\tawait listener.start()\n\t\t\t\t\t}\n\n\t\t\t\t\t// Check listener health\n\t\t\t\t\tif (state.listenerRunning) {\n\t\t\t\t\t\tstate.lastOkAt = Date.now()\n\t\t\t\t\t\tstate.consecutiveErrors = 0\n\t\t\t\t\t\tnextDelay = intervalMs\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthrow new Error(\"Message listener is not running\")\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\tstate.lastErrAt = Date.now()\n\t\t\t\t\tstate.consecutiveErrors += 1\n\t\t\t\t\tconst backoff = Math.min(\n\t\t\t\t\t\tmaxBackoffMs,\n\t\t\t\t\t\tbaseBackoffMs * 2 ** (state.consecutiveErrors - 1)\n\t\t\t\t\t)\n\t\t\t\t\tnextDelay = backoff\n\t\t\t\t\tconsole.error(\"[XMTP Background] Supervisor error:\", error)\n\n\t\t\t\t\t// Try to restart the listener\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (state.listenerRunning) {\n\t\t\t\t\t\t\tawait listener.stop()\n\t\t\t\t\t\t}\n\t\t\t\t\t\tawait sleep(1000) // Wait 1 second before restarting\n\t\t\t\t\t} catch (restartError) {\n\t\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t\t\"[XMTP Background] Error restarting listener:\",\n\t\t\t\t\t\t\trestartError\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Sleep until next iteration\n\t\t\t\tawait sleep(nextDelay)\n\t\t\t}\n\n\t\t\t// Cleanup on exit\n\t\t\ttry {\n\t\t\t\tif (state.listenerRunning) {\n\t\t\t\t\tawait listener.stop()\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\"[XMTP Background] Error stopping listener:\", error)\n\t\t\t}\n\n\t\t\tconsole.log(\"[XMTP Background] Supervisor stopped\")\n\t\t})()\n\n\t\tconsole.log(\n\t\t\t\"[XMTP Background] Message processor started (always-on, in-process)\"\n\t\t)\n\t}\n\n\t// Middleware is a pass-through; registering it ensures the processor is active\n\treturn async (_c, next) => next()\n}\n\n// Optional helpers to inspect/stop from your server code\nexport function getBgState(): BgState | undefined {\n\treturn (globalThis as any)[BG_STATE] as BgState | undefined\n}\n\nexport function stopBackground(): void {\n\tconst fn = (globalThis as any)[BG_STOP] as (() => void) | undefined\n\tif (fn) fn()\n}\n","import { Context } from \"hono\"\nimport jwt from \"jsonwebtoken\"\n\nexport interface XMTPToolsPayload {\n\taction: \"send\" | \"reply\" | \"react\" | \"transaction\" | \"blockchain-event\"\n\tconversationId: string\n\t// Action-specific data\n\tcontent?: string\n\treferenceMessageId?: string\n\temoji?: string\n\tactionType?: \"added\" | \"removed\"\n\tfromAddress?: string\n\tchainId?: string\n\tcalls?: Array<{\n\t\tto: string\n\t\tdata: string\n\t\tmetadata?: {\n\t\t\tdescription: string\n\t\t\ttransactionType: string\n\t\t}\n\t}>\n\t// Metadata\n\tissued: number\n\texpires: number\n}\n\n/**\n * Validates token and returns payload for both GET and POST endpoints\n *\n * @param {Context} c - Hono context object containing request information\n * @returns {XMTPToolsPayload | null} The validated payload or null if invalid\n *\n * @description\n * Supports two authentication methods:\n * - Authorization header with Bearer token (for POST endpoints)\n * - Query parameter token (for GET endpoints)\n *\n * @example\n * ```typescript\n * app.post(\"/api/endpoint\", async (c) => {\n * const payload = getValidatedPayload(c);\n * if (!payload) {\n * return c.json({ error: \"Invalid token\" }, 401);\n * }\n * // Use payload data\n * });\n * ```\n */\nexport function getValidatedPayload(c: Context): XMTPToolsPayload | null {\n\t// Try Authorization header first (for POST endpoints)\n\tconst authHeader = c.req.header(\"Authorization\")\n\tif (authHeader?.startsWith(\"Bearer \")) {\n\t\tconst token = authHeader.substring(7) // Remove \"Bearer \" prefix\n\t\treturn validateXMTPToolsToken(token)\n\t}\n\n\t// Fall back to query parameter (for GET endpoints)\n\tconst token = c.req.query(\"token\")\n\tif (!token) {\n\t\treturn null\n\t}\n\n\treturn validateXMTPToolsToken(token)\n}\n\n/**\n * JWT secret key used for signing and verifying tokens\n * Falls back to a development secret if XMTP_JWT_SECRET is not set\n */\nconst JWT_SECRET = process.env.XMTP_JWT_SECRET || \"fallback-secret-for-dev\"\n\n/**\n * API key used for simple authentication bypass\n * Falls back to a development key if XMTP_API_KEY is not set\n */\nconst API_KEY = process.env.XMTP_API_KEY || \"fallback-api-key-for-dev\"\n\n/**\n * JWT token expiry time in seconds (5 minutes)\n */\nconst JWT_EXPIRY = 5 * 60 // 5 minutes in seconds\n\n/**\n * Generates a signed JWT token for XMTP tools authentication\n *\n * @param {Omit<XMTPToolsPayload, \"issued\" | \"expires\">} payload - Token payload without timestamp fields\n * @returns {string} Signed JWT token\n *\n * @description\n * Creates a JWT token with automatic timestamp fields:\n * - issued: Current timestamp\n * - expires: Current timestamp + JWT_EXPIRY\n *\n * @example\n * ```typescript\n * const token = generateXMTPToolsToken({\n * action: \"send\",\n * conversationId: \"0x123...\"\n * });\n * ```\n */\nexport function generateXMTPToolsToken(\n\tpayload: Omit<XMTPToolsPayload, \"issued\" | \"expires\">\n): string {\n\tconst now = Math.floor(Date.now() / 1000)\n\tconst fullPayload: XMTPToolsPayload = {\n\t\t...payload,\n\t\tissued: now,\n\t\texpires: now + JWT_EXPIRY\n\t}\n\n\treturn jwt.sign(fullPayload, JWT_SECRET, {\n\t\texpiresIn: JWT_EXPIRY\n\t})\n}\n\n/**\n * Validates an XMTP tools token using either API key or JWT verification\n *\n * @param {string} token - Token to validate (either API key or JWT)\n * @returns {XMTPToolsPayload | null} Validated payload or null if invalid\n *\n * @description\n * Supports two authentication methods in order of precedence:\n * 1. API key authentication - Direct comparison with XMTP_API_KEY\n * 2. JWT token authentication - Signature verification and expiry check\n *\n * For API key authentication, returns a default payload with 1-hour expiry.\n * For JWT authentication, validates signature and checks expiry timestamp.\n *\n * @example\n * ```typescript\n * const payload = validateXMTPToolsToken(userToken);\n * if (payload) {\n * console.log(`Action: ${payload.action}`);\n * console.log(`Conversation: ${payload.conversationId}`);\n * }\n * ```\n */\nexport function validateXMTPToolsToken(token: string): XMTPToolsPayload | null {\n\t// First try API key authentication\n\tif (token === API_KEY) {\n\t\tconsole.log(\"🔑 [Auth] Using API key authentication\")\n\t\t// Return a valid payload for API key auth\n\t\tconst now = Math.floor(Date.now() / 1000)\n\t\treturn {\n\t\t\taction: \"send\", // Default action\n\t\t\tconversationId: \"\", // Will be filled by endpoint\n\t\t\tissued: now,\n\t\t\texpires: now + 3600 // API keys are valid for 1 hour\n\t\t}\n\t}\n\n\t// Then try JWT token authentication\n\ttry {\n\t\tconst decoded = jwt.verify(token, JWT_SECRET) as XMTPToolsPayload\n\t\tconsole.log(\"🔑 [Auth] Using JWT token authentication\")\n\n\t\t// Additional expiry check\n\t\tconst now = Math.floor(Date.now() / 1000)\n\t\tif (decoded.expires < now) {\n\t\t\tconsole.warn(\"🔒 XMTP tools token has expired\")\n\t\t\treturn null\n\t\t}\n\n\t\treturn decoded\n\t} catch (error) {\n\t\tconsole.error(\n\t\t\t\"🔒 Invalid XMTP tools token and not matching API key:\",\n\t\t\terror\n\t\t)\n\t\treturn null\n\t}\n}\n","import type { HonoVariables } from \"@hybrd/xmtp\"\nimport type { Hono } from \"hono\"\n\n/**\n * Plugin interface for extending the agent's Hono app\n *\n * @description\n * Plugins allow you to extend the agent's HTTP server with additional\n * routes, middleware, and functionality. Each plugin receives the Hono\n * app instance and can modify it as needed.\n *\n * @template T - Optional context type that can be passed to the plugin\n */\nexport interface Plugin<T = Record<string, never>> {\n\t/**\n\t * Unique identifier for the plugin\n\t */\n\tname: string\n\n\t/**\n\t * Optional description of what the plugin does\n\t */\n\tdescription?: string\n\n\t/**\n\t * Function that applies the plugin to the Hono app\n\t *\n\t * @param app - The Hono app instance to extend\n\t * @param context - Optional context data passed to the plugin\n\t */\n\tapply: (\n\t\tapp: Hono<{ Variables: HonoVariables }>,\n\t\tcontext?: T\n\t) => void | Promise<void>\n}\n\n/**\n * Plugin registry that manages all registered plugins\n *\n * @description\n * The plugin registry allows you to register, configure, and apply\n * plugins to Hono apps. It provides a centralized way to manage\n * plugin dependencies and execution order.\n */\nexport class PluginRegistry<T = Record<string, never>> {\n\tprivate plugins: Map<string, Plugin<T>> = new Map()\n\n\t/**\n\t * Registers a plugin with the registry\n\t *\n\t * @param plugin - The plugin to register\n\t * @throws {Error} If a plugin with the same name is already registered\n\t */\n\tregister(plugin: Plugin<T>): void {\n\t\tif (this.plugins.has(plugin.name)) {\n\t\t\tthrow new Error(`Plugin \"${plugin.name}\" is already registered`)\n\t\t}\n\n\t\tthis.plugins.set(plugin.name, plugin)\n\t}\n\n\t/**\n\t * Unregisters a plugin from the registry\n\t *\n\t * @param name - The name of the plugin to unregister\n\t * @returns True if the plugin was unregistered, false if it wasn't found\n\t */\n\tunregister(name: string): boolean {\n\t\treturn this.plugins.delete(name)\n\t}\n\n\t/**\n\t * Gets a plugin by name\n\t *\n\t * @param name - The name of the plugin to retrieve\n\t * @returns The plugin if found, undefined otherwise\n\t */\n\tget(name: string): Plugin<T> | undefined {\n\t\treturn this.plugins.get(name)\n\t}\n\n\t/**\n\t * Gets all registered plugins\n\t *\n\t * @returns Array of all registered plugins\n\t */\n\tgetAll(): Plugin<T>[] {\n\t\treturn Array.from(this.plugins.values())\n\t}\n\n\t/**\n\t * Checks if a plugin is registered\n\t *\n\t * @param name - The name of the plugin to check\n\t * @returns True if the plugin is registered, false otherwise\n\t */\n\thas(name: string): boolean {\n\t\treturn this.plugins.has(name)\n\t}\n\n\t/**\n\t * Applies all registered plugins to a Hono app\n\t *\n\t * @param app - The Hono app instance to extend\n\t * @param context - Optional context data passed to all plugins\n\t */\n\tasync applyAll(\n\t\tapp: Hono<{ Variables: HonoVariables }>,\n\t\tcontext?: T\n\t): Promise<void> {\n\t\tconst plugins = this.getAll()\n\n\t\tfor (const plugin of plugins) {\n\t\t\ttry {\n\t\t\t\tconsole.log(`🔌 Applying plugin: ${plugin.name}`)\n\t\t\t\tawait plugin.apply(app, context)\n\t\t\t\tconsole.log(`✅ Plugin applied: ${plugin.name}`)\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(`❌ Failed to apply plugin ${plugin.name}:`, error)\n\t\t\t\tthrow error\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Clears all registered plugins\n\t */\n\tclear(): void {\n\t\tthis.plugins.clear()\n\t}\n\n\t/**\n\t * Gets the number of registered plugins\n\t */\n\tget size(): number {\n\t\treturn this.plugins.size\n\t}\n}\n\n/**\n * Creates a plugin that mounts routes at a specific path\n *\n * @param name - Plugin name\n * @param path - Path to mount the routes at\n * @param routes - Hono app containing the routes to mount\n * @returns A plugin that mounts the routes\n */\nexport function createRoutePlugin(\n\tname: string,\n\tpath: string,\n\troutes: Hono<{ Variables: HonoVariables }>\n): Plugin {\n\treturn {\n\t\tname,\n\t\tdescription: `Mounts routes at ${path}`,\n\t\tapply: (app: Hono<{ Variables: HonoVariables }>) => {\n\t\t\tapp.route(path, routes)\n\t\t}\n\t}\n}\n\n/**\n * Creates a plugin that applies middleware\n *\n * @param name - Plugin name\n * @param middleware - Middleware function to apply\n * @returns A plugin that applies the middleware\n */\nexport function createMiddlewarePlugin(\n\tname: string,\n\tmiddleware: (app: Hono<{ Variables: HonoVariables }>) => void\n): Plugin {\n\treturn {\n\t\tname,\n\t\tdescription: `Applies middleware: ${name}`,\n\t\tapply: middleware\n\t}\n}\n","import { Tool as AISDKTool, type UIMessage } from \"ai\"\nimport { z } from \"zod\"\nimport { AgentRuntime } from \"../types\"\n\ntype DefaultRuntimeExtension = Record<string, never>\n\n/**\n * Configuration interface for creating custom tools that integrate with AI SDK.\n */\nexport interface ToolConfig<\n\tTInput extends z.ZodTypeAny = z.ZodTypeAny,\n\tTOutput extends z.ZodTypeAny = z.ZodTypeAny,\n\tTRuntimeExtension = DefaultRuntimeExtension\n> {\n\t/** Unique identifier for the tool */\n\tid: string\n\t/** Human-readable description of what the tool does */\n\tdescription: string\n\t/** Zod schema for validating tool input */\n\tinputSchema: TInput\n\t/** Optional Zod schema for validating tool output */\n\toutputSchema?: TOutput\n\t/** Function that executes the tool's logic */\n\texecute: (args: {\n\t\tinput: z.infer<TInput>\n\t\truntime: AgentRuntime & TRuntimeExtension\n\t\tmessages: UIMessage[]\n\t}) => Promise<z.infer<TOutput>>\n}\n\n/**\n * Internal tool interface used throughout the agent framework.\n * Similar to ToolConfig but without the ID field, used after tool creation.\n */\nexport interface Tool<\n\tTInput extends z.ZodTypeAny = z.ZodTypeAny,\n\tTOutput extends z.ZodTypeAny = z.ZodTypeAny,\n\tTRuntimeExtension = DefaultRuntimeExtension\n> {\n\t/** Human-readable description of what the tool does */\n\tdescription: string\n\t/** Zod schema for validating tool input */\n\tinputSchema: TInput\n\t/** Optional Zod schema for validating tool output */\n\toutputSchema?: TOutput\n\t/** Function that executes the tool's logic */\n\texecute: (args: {\n\t\tinput: z.infer<TInput>\n\t\truntime: AgentRuntime & TRuntimeExtension\n\t\tmessages: UIMessage[]\n\t}) => Promise<z.infer<TOutput>>\n}\n\n/**\n * Factory function to create tools with custom runtime extensions.\n * Provides proper type inference for input/output schemas and runtime extensions.\n */\nexport function toolFactory<TRuntimeExtension = DefaultRuntimeExtension>() {\n\treturn <\n\t\tTInput extends z.ZodTypeAny,\n\t\tTOutput extends z.ZodTypeAny = z.ZodTypeAny\n\t>(\n\t\tconfig: ToolConfig<TInput, TOutput, TRuntimeExtension>\n\t): Tool<TInput, TOutput, TRuntimeExtension> => {\n\t\treturn {\n\t\t\tdescription: config.description,\n\t\t\tinputSchema: config.inputSchema,\n\t\t\toutputSchema: config.outputSchema,\n\t\t\texecute: async (args) => {\n\t\t\t\tconst input = config.inputSchema.parse(args.input)\n\t\t\t\tconst result = await config.execute({\n\t\t\t\t\tinput,\n\t\t\t\t\truntime: args.runtime,\n\t\t\t\t\tmessages: args.messages\n\t\t\t\t})\n\t\t\t\tif (config.outputSchema) {\n\t\t\t\t\treturn config.outputSchema.parse(result)\n\t\t\t\t}\n\t\t\t\treturn result\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Default tool factory with no runtime extensions.\n * Type-safe at creation time with proper schema inference.\n */\nexport const createTool = toolFactory()\n\n/**\n * Converts a custom Tool instance to AI SDK's tool format.\n * This adapter enables our tools to work with AI SDK's generateText/streamText functions.\n */\nexport function toAISDKTool<\n\tTRuntimeExtension = DefaultRuntimeExtension,\n\tTInput extends z.ZodTypeAny = z.ZodTypeAny,\n\tTOutput extends z.ZodTypeAny = z.ZodTypeAny\n>(\n\ttool: Tool<TInput, TOutput, TRuntimeExtension>,\n\truntime: AgentRuntime & TRuntimeExtension,\n\tmessages: UIMessage[]\n): AISDKTool {\n\treturn {\n\t\tdescription: tool.description,\n\t\tinputSchema: tool.inputSchema,\n\t\texecute: async (args: z.infer<TInput>) => {\n\t\t\treturn tool.execute({\n\t\t\t\tinput: args,\n\t\t\t\truntime,\n\t\t\t\tmessages\n\t\t\t})\n\t\t}\n\t}\n}\n\n/**\n * Converts a collection of custom tools to AI SDK format.\n * Useful for batch conversion when setting up multiple tools for AI SDK usage.\n */\nexport function toAISDKTools<\n\tTRuntimeExtension = DefaultRuntimeExtension,\n\tTInput extends z.ZodTypeAny = z.ZodTypeAny,\n\tTOutput extends z.ZodTypeAny = z.ZodTypeAny\n>(\n\ttools: Record<string, Tool<TInput, TOutput, TRuntimeExtension>>,\n\truntime: AgentRuntime & TRuntimeExtension,\n\tmessages: UIMessage[]\n): Record<string, AISDKTool> {\n\tconst convertedTools: Record<string, AISDKTool> = {}\n\n\tfor (const [name, tool] of Object.entries(tools)) {\n\t\tconvertedTools[name] = toAISDKTool(tool, runtime, messages)\n\t}\n\n\treturn convertedTools\n}\n","/**\n * @fileoverview Blockchain Tools for Crypto Agents\n *\n * This module provides comprehensive blockchain interaction tools for crypto-enabled agents.\n * Supports Ethereum and other EVM-compatible chains with features like balance checking,\n * transaction sending, contract interaction, and more.\n *\n * @module BlockchainTools\n */\n\nimport {\n\tcreatePublicClient,\n\tcreateWalletClient,\n\tformatEther,\n\thttp,\n\tparseEther,\n\ttype Address,\n\ttype Hash\n} from \"viem\"\nimport { privateKeyToAccount } from \"viem/accounts\"\nimport {\n\tarbitrum,\n\tbase,\n\tmainnet,\n\toptimism,\n\tpolygon,\n\tsepolia\n} from \"viem/chains\"\nimport { z } from \"zod\"\nimport { createTool } from \"../core/tool\"\n\n// Supported chains configuration\nconst SUPPORTED_CHAINS = {\n\tmainnet,\n\tsepolia,\n\tpolygon,\n\tarbitrum,\n\toptimism,\n\tbase\n} as const\n\ntype SupportedChain = keyof typeof SUPPORTED_CHAINS\n\n// Runtime extension interface for blockchain tools\nexport interface BlockchainRuntimeExtension {\n\trpcUrl?: string\n\tprivateKey?: string\n\tdefaultChain?: SupportedChain\n}\n\n/**\n * Get Balance Tool\n *\n * Retrieves the native token balance for a given address on a specified chain.\n *\n * @tool getBalance\n * @category Blockchain\n *\n * @param {string} address - The wallet address to check balance for\n * @param {string} [chain] - The blockchain network (defaults to mainnet)\n *\n * @returns {Promise<{success: boolean, balance: string, balanceWei: string, address: string, chain: string, error?: string}>}\n */\nexport const getBalanceTool = createTool({\n\tid: \"getBalance\",\n\tdescription:\n\t\t\"Get the native token balance for a wallet address on a blockchain\",\n\tinputSchema: z.object({\n\t\taddress: z.string().describe(\"The wallet address to check balance for\"),\n\t\tchain: z\n\t\t\t.enum([\"mainnet\", \"sepolia\", \"polygon\", \"arbitrum\", \"optimism\", \"base\"])\n\t\t\t.default(\"mainnet\")\n\t\t\t.describe(\"The blockchain network to check on\")\n\t}),\n\toutputSchema: z.object({\n\t\tsuccess: z.boolean(),\n\t\tbalance: z\n\t\t\t.string()\n\t\t\t.describe(\"Balance in human readable format (ETH, MATIC, etc.)\"),\n\t\tbalanceWei: z.string().describe(\"Balance in wei (smallest unit)\"),\n\t\taddress: z.string(),\n\t\tchain: z.string(),\n\t\terror: z.string().optional()\n\t}),\n\texecute: async ({ input, runtime }) => {\n\t\ttry {\n\t\t\tconst { address, chain } = input\n\t\t\tconst chainConfig = SUPPORTED_CHAINS[chain]\n\n\t\t\t// Use runtime RPC URL if provided, otherwise use default\n\t\t\tconst rpcUrl =\n\t\t\t\t(runtime as any).rpcUrl || chainConfig.rpcUrls.default.http[0]\n\n\t\t\tconst client = createPublicClient({\n\t\t\t\tchain: chainConfig,\n\t\t\t\ttransport: http(rpcUrl)\n\t\t\t})\n\n\t\t\tconsole.log(`🔍 [getBalance] Checking balance for ${address} on ${chain}`)\n\n\t\t\tconst balanceWei = await client.getBalance({\n\t\t\t\taddress: address as Address\n\t\t\t})\n\n\t\t\tconst balance = formatEther(balanceWei)\n\n\t\t\tconsole.log(\n\t\t\t\t`✅ [getBalance] Balance: ${balance} ${chainConfig.nativeCurrency.symbol}`\n\t\t\t)\n\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tbalance: `${balance} ${chainConfig.nativeCurrency.symbol}`,\n\t\t\t\tbalanceWei: balanceWei.toString(),\n\t\t\t\taddress,\n\t\t\t\tchain\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconst errorMessage =\n\t\t\t\terror instanceof Error ? error.message : String(error)\n\t\t\tconsole.error(\"❌ [getBalance] Error:\", errorMessage)\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\tbalance: \"0\",\n\t\t\t\tbalanceWei: \"0\",\n\t\t\t\taddress: input.address,\n\t\t\t\tchain: input.chain,\n\t\t\t\terror: errorMessage\n\t\t\t}\n\t\t}\n\t}\n})\n\n/**\n * Get Transaction Tool\n *\n * Retrieves transaction details by transaction hash.\n *\n * @tool getTransaction\n * @category Blockchain\n *\n * @param {string} hash - The transaction hash to look up\n * @param {string} [chain] - The blockchain network (defaults to mainnet)\n *\n * @returns {Promise<{success: boolean, transaction?: object, error?: string}>}\n */\nexport const getTransactionTool = createTool({\n\tid: \"getTransaction\",\n\tdescription: \"Get transaction details by transaction hash\",\n\tinputSchema: z.object({\n\t\thash: z.string().describe(\"The transaction hash to look up\"),\n\t\tchain: z\n\t\t\t.enum([\"mainnet\", \"sepolia\", \"polygon\", \"arbitrum\", \"optimism\", \"base\"])\n\t\t\t.default(\"mainnet\")\n\t\t\t.describe(\"The blockchain network to check on\")\n\t}),\n\toutputSchema: z.object({\n\t\tsuccess: z.boolean(),\n\t\ttransaction: z\n\t\t\t.object({\n\t\t\t\thash: z.string(),\n\t\t\t\tfrom: z.string(),\n\t\t\t\tto: z.string().nullable(),\n\t\t\t\tvalue: z.string(),\n\t\t\t\tgasUsed: z.string().optional(),\n\t\t\t\tgasPrice: z.string().optional(),\n\t\t\t\tblockNumber: z.string().optional(),\n\t\t\t\tstatus: z.string().optional()\n\t\t\t})\n\t\t\t.optional(),\n\t\terror: z.string().optional()\n\t}),\n\texecute: async ({ input, runtime }) => {\n\t\ttry {\n\t\t\tconst { hash, chain } = input\n\t\t\tconst chainConfig = SUPPORTED_CHAINS[chain]\n\n\t\t\tconst rpcUrl =\n\t\t\t\t(runtime as any).rpcUrl || chainConfig.rpcUrls.default.http[0]\n\n\t\t\tconst client = createPublicClient({\n\t\t\t\tchain: chainConfig,\n\t\t\t\ttransport: http(rpcUrl)\n\t\t\t})\n\n\t\t\tconsole.log(\n\t\t\t\t`🔍 [getTransaction] Looking up transaction ${hash} on ${chain}`\n\t\t\t)\n\n\t\t\tconst transaction = await client.getTransaction({\n\t\t\t\thash: hash as Hash\n\t\t\t})\n\n\t\t\tconst receipt = await client\n\t\t\t\t.getTransactionReceipt({\n\t\t\t\t\thash: hash as Hash\n\t\t\t\t})\n\t\t\t\t.catch(() => null) // Transaction might be pending\n\n\t\t\tconsole.log(\n\t\t\t\t`✅ [getTransaction] Found transaction from ${transaction.from} to ${transaction.to}`\n\t\t\t)\n\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\ttransaction: {\n\t\t\t\t\thash: transaction.hash,\n\t\t\t\t\tfrom: transaction.from,\n\t\t\t\t\tto: transaction.to,\n\t\t\t\t\tvalue: formatEther(transaction.value),\n\t\t\t\t\tgasUsed: receipt?.gasUsed.toString(),\n\t\t\t\t\tgasPrice: transaction.gasPrice?.toString(),\n\t\t\t\t\tblockNumber: transaction.blockNumber?.toString(),\n\t\t\t\t\tstatus:\n\t\t\t\t\t\treceipt?.status === \"success\"\n\t\t\t\t\t\t\t? \"success\"\n\t\t\t\t\t\t\t: receipt?.status === \"reverted\"\n\t\t\t\t\t\t\t\t? \"failed\"\n\t\t\t\t\t\t\t\t: \"pending\"\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconst errorMessage =\n\t\t\t\terror instanceof Error ? error.message : String(error)\n\t\t\tconsole.error(\"❌ [getTransaction] Error:\", errorMessage)\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: errorMessage\n\t\t\t}\n\t\t}\n\t}\n})\n\n/**\n * Send Transaction Tool\n *\n * Sends a native token transaction to another address.\n * Requires a private key to be configured in the runtime.\n *\n * @tool sendTransaction\n * @category Blockchain\n *\n * @param {string} to - The recipient address\n * @param {string} amount - The amount to send (in ETH, MATIC, etc.)\n * @param {string} [chain] - The blockchain network (defaults to mainnet)\n *\n * @returns {Promise<{success: boolean, hash?: string, error?: string}>}\n */\nexport const sendTransactionTool = createTool({\n\tid: \"sendTransaction\",\n\tdescription: \"Send native tokens to another address\",\n\tinputSchema: z.object({\n\t\tto: z.string().describe(\"The recipient address\"),\n\t\tamount: z.string().describe(\"The amount to send (in ETH, MATIC, etc.)\"),\n\t\tchain: z\n\t\t\t.enum([\"mainnet\", \"sepolia\", \"polygon\", \"arbitrum\", \"optimism\", \"base\"])\n\t\t\t.default(\"mainnet\")\n\t\t\t.describe(\"The blockchain network to send on\")\n\t}),\n\toutputSchema: z.object({\n\t\tsuccess: z.boolean(),\n\t\thash: z.string().optional(),\n\t\tfrom: z.string().optional(),\n\t\tto: z.string(),\n\t\tamount: z.string(),\n\t\tchain: z.string(),\n\t\terror: z.string().optional()\n\t}),\n\texecute: async ({ input, runtime }) => {\n\t\ttry {\n\t\t\tconst { to, amount, chain } = input\n\t\t\tconst chainConfig = SUPPORTED_CHAINS[chain]\n\n\t\t\tconst privateKey = (runtime as any).privateKey\n\t\t\tif (!privateKey) {\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\tto,\n\t\t\t\t\tamount,\n\t\t\t\t\tchain,\n\t\t\t\t\terror: \"Private key not configured in runtime\"\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst rpcUrl =\n\t\t\t\t(runtime as any).rpcUrl || chainConfig.rpcUrls.default.http[0]\n\t\t\tconst account = privateKeyToAccount(privateKey as `0x${string}`)\n\n\t\t\tconst client = createWalletClient({\n\t\t\t\taccount,\n\t\t\t\tchain: chainConfig,\n\t\t\t\ttransport: http(rpcUrl)\n\t\t\t})\n\n\t\t\tconsole.log(\n\t\t\t\t`💸 [sendTransaction] Sending ${amount} ${chainConfig.nativeCurrency.symbol} to ${to} on ${chain}`\n\t\t\t)\n\n\t\t\tconst hash = await client.sendTransaction({\n\t\t\t\tto: to as Address,\n\t\t\t\tvalue: parseEther(amount)\n\t\t\t})\n\n\t\t\tconsole.log(`✅ [sendTransaction] Transaction sent: ${hash}`)\n\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\thash,\n\t\t\t\tfrom: account.address,\n\t\t\t\tto,\n\t\t\t\tamount,\n\t\t\t\tchain\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconst errorMessage =\n\t\t\t\terror instanceof Error ? error.message : String(error)\n\t\t\tconsole.error(\"❌ [sendTransaction] Error:\", errorMessage)\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\tto: input.to,\n\t\t\t\tamount: input.amount,\n\t\t\t\tchain: input.chain,\n\t\t\t\terror: errorMessage\n\t\t\t}\n\t\t}\n\t}\n})\n\n/**\n * Get Block Tool\n *\n * Retrieves information about a specific block.\n *\n * @tool getBlock\n * @category Blockchain\n *\n * @param {string} [blockNumber] - Block number (defaults to latest)\n * @param {string} [chain] - The blockchain network (defaults to mainnet)\n *\n * @returns {Promise<{success: boolean, block?: object, error?: string}>}\n */\nexport const getBlockTool = createTool({\n\tid: \"getBlock\",\n\tdescription: \"Get information about a blockchain block\",\n\tinputSchema: z.object({\n\t\tblockNumber: z\n\t\t\t.string()\n\t\t\t.optional()\n\t\t\t.describe(\"Block number (defaults to latest)\"),\n\t\tchain: z\n\t\t\t.enum([\"mainnet\", \"sepolia\", \"polygon\", \"arbitrum\", \"optimism\", \"base\"])\n\t\t\t.default(\"mainnet\")\n\t\t\t.describe(\"The blockchain network to check on\")\n\t}),\n\toutputSchema: z.object({\n\t\tsuccess: z.boolean(),\n\t\tblock: z\n\t\t\t.object({\n\t\t\t\tnumber: z.string(),\n\t\t\t\thash: z.string(),\n\t\t\t\ttimestamp: z.string(),\n\t\t\t\ttransactionCount: z.number(),\n\t\t\t\tgasUsed: z.string(),\n\t\t\t\tgasLimit: z.string()\n\t\t\t})\n\t\t\t.optional(),\n\t\terror: z.string().optional()\n\t}),\n\texecute: async ({ input, runtime }) => {\n\t\ttry {\n\t\t\tconst { blockNumber, chain } = input\n\t\t\tconst chainConfig = SUPPORTED_CHAINS[chain]\n\n\t\t\tconst rpcUrl =\n\t\t\t\t(runtime as any).rpcUrl || chainConfig.rpcUrls.default.http[0]\n\n\t\t\tconst client = createPublicClient({\n\t\t\t\tchain: chainConfig,\n\t\t\t\ttransport: http(rpcUrl)\n\t\t\t})\n\n\t\t\tconsole.log(\n\t\t\t\t`🔍 [getBlock] Getting block ${blockNumber || \"latest\"} on ${chain}`\n\t\t\t)\n\n\t\t\tconst block = await client.getBlock({\n\t\t\t\tblockNumber: blockNumber ? BigInt(blockNumber) : undefined\n\t\t\t})\n\n\t\t\tconsole.log(\n\t\t\t\t`✅ [getBlock] Found block ${block.number} with ${block.transactions.length} transactions`\n\t\t\t)\n\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tblock: {\n\t\t\t\t\tnumber: block.number.toString(),\n\t\t\t\t\thash: block.hash,\n\t\t\t\t\ttimestamp: block.timestamp.toString(),\n\t\t\t\t\ttransactionCount: block.transactions.length,\n\t\t\t\t\tgasUsed: block.gasUsed.toString(),\n\t\t\t\t\tgasLimit: block.gasLimit.toString()\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconst errorMessage =\n\t\t\t\terror instanceof Error ? error.message : String(error)\n\t\t\tconsole.error(\"❌ [getBlock] Error:\", errorMessage)\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: errorMessage\n\t\t\t}\n\t\t}\n\t}\n})\n\n/**\n * Get Gas Price Tool\n *\n * Retrieves current gas price information for a blockchain.\n *\n * @tool getGasPrice\n * @category Blockchain\n *\n * @param {string} [chain] - The blockchain network (defaults to mainnet)\n *\n * @returns {Promise<{success: boolean, gasPrice?: string, error?: string}>}\n */\nexport const getGasPriceTool = createTool({\n\tid: \"getGasPrice\",\n\tdescription: \"Get current gas price for a blockchain\",\n\tinputSchema: z.object({\n\t\tchain: z\n\t\t\t.enum([\"mainnet\", \"sepolia\", \"polygon\", \"arbitrum\", \"optimism\", \"base\"])\n\t\t\t.default(\"mainnet\")\n\t\t\t.describe(\"The blockchain network to check on\")\n\t}),\n\toutputSchema: z.object({\n\t\tsuccess: z.boolean(),\n\t\tgasPrice: z.string().optional().describe(\"Gas price in gwei\"),\n\t\tgasPriceWei: z.string().optional().describe(\"Gas price in wei\"),\n\t\tchain: z.string(),\n\t\terror: z.string().optional()\n\t}),\n\texecute: async ({ input, runtime }) => {\n\t\ttry {\n\t\t\tconst { chain } = input\n\t\t\tconst chainConfig = SUPPORTED_CHAINS[chain]\n\n\t\t\tconst rpcUrl =\n\t\t\t\t(runtime as any).rpcUrl || chainConfig.rpcUrls.default.http[0]\n\n\t\t\tconst client = createPublicClient({\n\t\t\t\tchain: chainConfig,\n\t\t\t\ttransport: http(rpcUrl)\n\t\t\t})\n\n\t\t\tconsole.log(`⛽ [getGasPrice] Getting gas price for ${chain}`)\n\n\t\t\tconst gasPrice = await client.getGasPrice()\n\t\t\tconst gasPriceGwei = formatEther(gasPrice * BigInt(1000000000)) // Convert to gwei\n\n\t\t\tconsole.log(`✅ [getGasPrice] Current gas price: ${gasPriceGwei} gwei`)\n\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tgasPrice: `${gasPriceGwei} gwei`,\n\t\t\t\tgasPriceWei: gasPrice.toString(),\n\t\t\t\tchain\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconst errorMessage =\n\t\t\t\terror instanceof Error ? error.message : String(error)\n\t\t\tconsole.error(\"❌ [getGasPrice] Error:\", errorMessage)\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\tchain: input.chain,\n\t\t\t\terror: errorMessage\n\t\t\t}\n\t\t}\n\t}\n})\n\n/**\n * Estimate Gas Tool\n *\n * Estimates gas required for a transaction.\n *\n * @tool estimateGas\n * @category Blockchain\n *\n * @param {string} to - The recipient address\n * @param {string} [amount] - The amount to send (defaults to 0)\n * @param {string} [data] - Transaction data (for contract calls)\n * @param {string} [chain] - The blockchain network (defaults to mainnet)\n *\n * @returns {Promise<{success: boolean, gasEstimate?: string, error?: string}>}\n */\nexport const estimateGasTool = createTool({\n\tid: \"estimateGas\",\n\tdescription: \"Estimate gas required for a transaction\",\n\tinputSchema: z.object({\n\t\tto: z.string().describe(\"The recipient address\"),\n\t\tamount: z\n\t\t\t.string()\n\t\t\t.default(\"0\")\n\t\t\t.describe(\"The amount to send (defaults to 0)\"),\n\t\tdata: z\n\t\t\t.string()\n\t\t\t.optional()\n\t\t\t.describe(\"Transaction data (for contract calls)\"),\n\t\tchain: z\n\t\t\t.enum([\"mainnet\", \"sepolia\", \"polygon\", \"arbitrum\", \"optimism\", \"base\"])\n\t\t\t.default(\"mainnet\")\n\t\t\t.describe(\"The blockchain network to estimate on\")\n\t}),\n\toutputSchema: z.object({\n\t\tsuccess: z.boolean(),\n\t\tgasEstimate: z.string().optional(),\n\t\tto: z.string(),\n\t\tamount: z.string(),\n\t\tchain: z.string(),\n\t\terror: z.string().optional()\n\t}),\n\texecute: async ({ input, runtime }) => {\n\t\ttry {\n\t\t\tconst { to, amount, data, chain } = input\n\t\t\tconst chainConfig = SUPPORTED_CHAINS[chain]\n\n\t\t\tconst privateKey = (runtime as any).privateKey\n\t\t\tif (!privateKey) {\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\tto,\n\t\t\t\t\tamount,\n\t\t\t\t\tchain,\n\t\t\t\t\terror: \"Private key not configured in runtime\"\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst rpcUrl =\n\t\t\t\t(runtime as any).rpcUrl || chainConfig.rpcUrls.default.http[0]\n\t\t\tconst account = privateKeyToAccount(privateKey as `0x${string}`)\n\n\t\t\tconst client = createPublicClient({\n\t\t\t\tchain: chainConfig,\n\t\t\t\ttransport: http(rpcUrl)\n\t\t\t})\n\n\t\t\tconsole.log(\n\t\t\t\t`⛽ [estimateGas] Estimating gas for transaction to ${to} on ${chain}`\n\t\t\t)\n\n\t\t\tconst gasEstimate = await client.estimateGas({\n\t\t\t\taccount: account.address,\n\t\t\t\tto: to as Address,\n\t\t\t\tvalue: parseEther(amount),\n\t\t\t\tdata: data as `0x${string}` | undefined\n\t\t\t})\n\n\t\t\tconsole.log(`✅ [estimateGas] Estimated gas: ${gasEstimate.toString()}`)\n\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tgasEstimate: gasEstimate.toString(),\n\t\t\t\tto,\n\t\t\t\tamount,\n\t\t\t\tchain\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconst errorMessage =\n\t\t\t\terror instanceof Error ? error.message : String(error)\n\t\t\tconsole.error(\"❌ [estimateGas] Error:\", errorMessage)\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\tto: input.to,\n\t\t\t\tamount: input.amount,\n\t\t\t\tchain: input.chain,\n\t\t\t\terror: errorMessage\n\t\t\t}\n\t\t}\n\t}\n})\n\n/**\n * Collection of blockchain tools for crypto agents\n *\n * These tools provide comprehensive blockchain interaction capabilities including\n * balance checking, transaction sending, gas estimation, and more.\n *\n * @namespace blockchainTools\n *\n * @property {Tool} getBalance - Get native token balance for an address\n * @property {Tool} getTransaction - Get transaction details by hash\n * @property {Tool} sendTransaction - Send native tokens to another address\n * @property {Tool} getBlock - Get information about a blockchain block\n * @property {Tool} getGasPrice - Get current gas price for a blockchain\n * @property {Tool} estimateGas - Estimate gas required for a transaction\n */\nexport const blockchainTools = {\n\tgetBalance: getBalanceTool,\n\tgetTransaction: getTransactionTool,\n\tsendTransaction: sendTransactionTool,\n\tgetBlock: getBlockTool,\n\tgetGasPrice: getGasPriceTool,\n\testimateGas: estimateGasTool\n}\n","/**\n * @fileoverview XMTP Communication Tools for Crypto Agents\n *\n * This module provides comprehensive XMTP messaging tools for crypto-enabled agents.\n * Includes capabilities for sending messages, replies, reactions, and managing conversations.\n *\n * @module XMTPTools\n */\n\nimport { z } from \"zod\"\nimport { createTool } from \"../core/tool\"\n\n/**\n * Send Reaction Tool\n *\n * Sends an emoji reaction to a specific message to indicate the message has been seen.\n * This is used to acknowledge receipt of messages before responding.\n *\n * @tool sendReaction\n * @category Communication\n *\n * @param {string} emoji - The emoji to send as a reaction (defaults to 👀)\n * @param {string} [referenceMessageId] - The message ID to react to (uses current message if not provided)\n *\n * @returns {Promise<{success: boolean, emoji: string, error?: string}>}\n */\nexport const sendReactionTool = createTool({\n\tid: \"sendReaction\",\n\tdescription:\n\t\t\"Send an emoji reaction to a message to indicate it has been seen\",\n\tinputSchema: z.object({\n\t\temoji: z\n\t\t\t.string()\n\t\t\t.default(\"👀\")\n\t\t\t.describe(\n\t\t\t\t\"The emoji to send as a reaction (supports common emoji like 👍, ❤️, 🔥, etc.)\"\n\t\t\t),\n\t\treferenceMessageId: z\n\t\t\t.string()\n\t\t\t.optional()\n\t\t\t.describe(\n\t\t\t\t\"The message ID to react to (uses current message if not provided)\"\n\t\t\t)\n\t}),\n\toutputSchema: z.object({\n\t\tsuccess: z.boolean(),\n\t\temoji: z.string(),\n\t\terror: z.string().optional()\n\t}),\n\texecute: async ({ input, runtime }) => {\n\t\ttry {\n\t\t\tconst xmtpClient = runtime.xmtpClient\n\t\t\tconst currentMessage = runtime.message\n\n\t\t\tif (!xmtpClient) {\n\t\t\t\tconst errorMsg = \"❌ XMTP service not available\"\n\t\t\t\treturn { success: false, emoji: input.emoji, error: errorMsg }\n\t\t\t}\n\n\t\t\tif (!currentMessage) {\n\t\t\t\tconst errorMsg = \"❌ No message to react to\"\n\t\t\t\treturn { success: false, emoji: input.emoji, error: errorMsg }\n\t\t\t}\n\n\t\t\t// Use provided reference message ID or current message ID\n\t\t\tconst messageIdToReactTo = input.referenceMessageId || currentMessage.id\n\n\t\t\tconsole.log(\n\t\t\t\t`👀 [sendReaction] Sending ${input.emoji} reaction to message ${messageIdToReactTo}`\n\t\t\t)\n\n\t\t\tconst reactionResult = await xmtpClient.sendReaction({\n\t\t\t\tmessageId: messageIdToReactTo,\n\t\t\t\temoji: input.emoji,\n\t\t\t\taction: \"added\"\n\t\t\t})\n\n\t\t\tif (!reactionResult.success) {\n\t\t\t\tconst errorMsg = `❌ Failed to send reaction: ${reactionResult.error || \"Unknown error\"}`\n\t\t\t\treturn { success: false, emoji: input.emoji, error: errorMsg }\n\t\t\t}\n\n\t\t\tconsole.log(`✅ [sendReaction] Successfully sent ${input.emoji} reaction`)\n\t\t\treturn { success: true, emoji: input.emoji }\n\t\t} catch (error) {\n\t\t\tconst errorMessage =\n\t\t\t\terror instanceof Error ? error.message : String(error)\n\t\t\tconsole.error(\"❌ [sendReaction] Error:\", errorMessage)\n\t\t\treturn { success: false, emoji: input.emoji, error: errorMessage }\n\t\t}\n\t}\n})\n\n/**\n * Send Message Tool\n *\n * Sends a message to an XMTP conversation or creates a new conversation.\n *\n * @tool sendMessage\n * @category Communication\n *\n * @param {string} content - The message content to send\n * @param {string} [recipientAddress] - Recipient address for new conversations\n * @param {string} [conversationId] - Existing conversation ID to send to\n *\n * @returns {Promise<{success: boolean, messageId?: string, conversationId?: string, error?: string}>}\n */\nexport const sendMessageTool = createTool({\n\tid: \"sendMessage\",\n\tdescription: \"Send a message to an XMTP conversation\",\n\tinputSchema: z\n\t\t.object({\n\t\t\tcontent: z.string().describe(\"The message content to send\"),\n\t\t\trecipientAddress: z\n\t\t\t\t.string()\n\t\t\t\t.optional()\n\t\t\t\t.describe(\"Recipient address for new conversations\"),\n\t\t\tconversationId: z\n\t\t\t\t.string()\n\t\t\t\t.optional()\n\t\t\t\t.describe(\"Existing conversation ID to send to\")\n\t\t})\n\t\t.refine((data) => data.recipientAddress || data.conversationId, {\n\t\t\tmessage: \"Either recipientAddress or conversationId must be provided\"\n\t\t}),\n\toutputSchema: z.object({\n\t\tsuccess: z.boolean(),\n\t\tmessageId: z.string().optional(),\n\t\tconversationId: z.string().optional(),\n\t\tcontent: z.string(),\n\t\terror: z.string().optional()\n\t}),\n\texecute: async ({ input, runtime }) => {\n\t\ttry {\n\t\t\tconst xmtpClient = runtime.xmtpClient\n\t\t\tconst { content, recipientAddress, conversationId } = input\n\n\t\t\tif (!xmtpClient) {\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\tcontent,\n\t\t\t\t\terror: \"XMTP service not available\"\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconsole.log(\n\t\t\t\t`💬 [sendMessage] Sending message: \"${content.substring(0, 50)}${content.length > 50 ? \"...\" : \"\"}\"`\n\t\t\t)\n\n\t\t\tlet targetConversationId = conversationId\n\n\t\t\t// If no conversation ID provided, create or find conversation with recipient\n\t\t\tif (!targetConversationId && recipientAddress) {\n\t\t\t\tconsole.log(\n\t\t\t\t\t`🔍 [sendMessage] Creating/finding conversation with ${recipientAddress}`\n\t\t\t\t)\n\t\t\t\t// This would depend on your XMTP client implementation\n\t\t\t\t// For now, we'll assume the client handles conversation creation\n\t\t\t\ttargetConversationId = recipientAddress // Simplified for this example\n\t\t\t}\n\n\t\t\t// Send the message using the XMTP client\n\t\t\tconst messageResult = await xmtpClient.sendMessage({\n\t\t\t\tcontent\n\t\t\t})\n\n\t\t\tif (!messageResult.success) {\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\tcontent,\n\t\t\t\t\terror: messageResult.error || \"Failed to send message\"\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconsole.log(`✅ [sendMessage] Message sent successfully`)\n\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tmessageId: messageResult.data?.conversationId,\n\t\t\t\tconversationId: messageResult.data?.conversationId,\n\t\t\t\tcontent\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconst errorMessage =\n\t\t\t\terror instanceof Error ? error.message : String(error)\n\t\t\tconsole.error(\"❌ [sendMessage] Error:\", errorMessage)\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\tcontent: input.content,\n\t\t\t\terror: errorMessage\n\t\t\t}\n\t\t}\n\t}\n})\n\n/**\n * Send Reply Tool\n *\n * Sends a reply to a specific message in an XMTP conversation.\n *\n * @tool sendReply\n * @category Communication\n *\n * @param {string} content - The reply content to send\n * @param {string} [replyToMessageId] - Message ID to reply to (uses current message if not provided)\n *\n * @returns {Promise<{success: boolean, messageId?: string, replyToMessageId?: string, error?: string}>}\n */\nexport const sendReplyTool = createTool({\n\tid: \"sendReply\",\n\tdescription: \"Send a reply to a specific message in an XMTP conversation\",\n\tinputSchema: z.object({\n\t\tcontent: z.string().describe(\"The reply content to send\"),\n\t\treplyToMessageId: z\n\t\t\t.string()\n\t\t\t.optional()\n\t\t\t.describe(\"Message ID to reply to (uses current message if not provided)\")\n\t}),\n\toutputSchema: z.object({\n\t\tsuccess: z.boolean(),\n\t\tmessageId: z.string().optional(),\n\t\treplyToMessageId: z.string().optional(),\n\t\tcontent: z.string(),\n\t\terror: z.string().optional()\n\t}),\n\texecute: async ({ input, runtime }) => {\n\t\ttry {\n\t\t\tconst xmtpClient = runtime.xmtpClient\n\t\t\tconst currentMessage = runtime.message\n\t\t\tconst { content, replyToMessageId } = input\n\n\t\t\tif (!xmtpClient) {\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\tcontent,\n\t\t\t\t\terror: \"XMTP service not available\"\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!currentMessage && !replyToMessageId) {\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\tcontent,\n\t\t\t\t\terror: \"No message to reply to\"\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst targetMessageId = replyToMessageId || currentMessage?.id\n\n\t\t\tconsole.log(\n\t\t\t\t`↩️ [sendReply] Sending reply to message ${targetMessageId}: \"${content.substring(0, 50)}${content.length > 50 ? \"...\" : \"\"}\"`\n\t\t\t)\n\n\t\t\tconst replyResult = await xmtpClient.sendReply({\n\t\t\t\tcontent,\n\t\t\t\tmessageId: targetMessageId\n\t\t\t})\n\n\t\t\tif (!replyResult.success) {\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\tcontent,\n\t\t\t\t\treplyToMessageId: targetMessageId,\n\t\t\t\t\terror: replyResult.error || \"Failed to send reply\"\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconsole.log(`✅ [sendReply] Reply sent successfully`)\n\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tmessageId: replyResult.data?.conversationId,\n\t\t\t\treplyToMessageId: targetMessageId,\n\t\t\t\tcontent\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconst errorMessage =\n\t\t\t\terror instanceof Error ? error.message : String(error)\n\t\t\tconsole.error(\"❌ [sendReply] Error:\", errorMessage)\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\tcontent: input.content,\n\t\t\t\treplyToMessageId: input.replyToMessageId,\n\t\t\t\terror: errorMessage\n\t\t\t}\n\t\t}\n\t}\n})\n\n/**\n * Get Message Tool\n *\n * Retrieves a specific message by ID from the XMTP service.\n *\n * @tool getMessage\n * @category Communication\n *\n * @param {string} messageId - The message ID to retrieve\n *\n * @returns {Promise<{success: boolean, message?: object, error?: string}>}\n */\nexport const getMessageTool = createTool({\n\tid: \"getMessage\",\n\tdescription: \"Get a specific message by ID from XMTP\",\n\tinputSchema: z.object({\n\t\tmessageId: z.string().describe(\"The message ID to retrieve\")\n\t}),\n\toutputSchema: z.object({\n\t\tsuccess: z.boolean(),\n\t\tmessage: z\n\t\t\t.object({\n\t\t\t\tid: z.string(),\n\t\t\t\tconversationId: z.string(),\n\t\t\t\tcontent: z.union([z.string(), z.record(z.unknown())]),\n\t\t\t\tsenderInboxId: z.string(),\n\t\t\t\tsentAt: z.string(),\n\t\t\t\tcontentType: z\n\t\t\t\t\t.object({\n\t\t\t\t\t\ttypeId: z.string(),\n\t\t\t\t\t\tauthorityId: z.string().optional(),\n\t\t\t\t\t\tversionMajor: z.number().optional(),\n\t\t\t\t\t\tversionMinor: z.number().optional()\n\t\t\t\t\t})\n\t\t\t\t\t.optional()\n\t\t\t})\n\t\t\t.optional(),\n\t\terror: z.string().optional()\n\t}),\n\texecute: async ({ input, runtime }) => {\n\t\ttry {\n\t\t\tconst xmtpClient = runtime.xmtpClient\n\t\t\tconst { messageId } = input\n\n\t\t\tif (!xmtpClient) {\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\terror: \"XMTP service not available\"\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconsole.log(`📜 [getMessage] Retrieving message ${messageId}`)\n\n\t\t\tconst messageResult = await xmtpClient.getMessage({\n\t\t\t\tmessageId\n\t\t\t})\n\n\t\t\tif (!messageResult.success) {\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\terror: messageResult.error || \"Failed to get message\"\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconsole.log(\n\t\t\t\t`✅ [getMessage] Retrieved message from ${messageResult.data?.senderInboxId}`\n\t\t\t)\n\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tmessage: messageResult.data\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconst errorMessage =\n\t\t\t\terror instanceof Error ? error.message : String(error)\n\t\t\tconsole.error(\"❌ [getMessage] Error:\", errorMessage)\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: errorMessage\n\t\t\t}\n\t\t}\n\t}\n})\n\n/**\n * Collection of XMTP communication tools for crypto agents\n *\n * These tools provide comprehensive messaging capabilities including sending messages,\n * replies, reactions, and retrieving message information.\n *\n * @namespace xmtpTools\n *\n * @property {Tool} sendMessage - Send a message to an XMTP conversation\n * @property {Tool} sendReply - Send a reply to a specific message\n * @property {Tool} sendReaction - Send an emoji reaction to a message\n * @property {Tool} getMessage - Get a specific message by ID\n */\nexport const xmtpTools = {\n\tsendMessage: sendMessageTool,\n\tsendReply: sendReplyTool,\n\tsendReaction: sendReactionTool,\n\tgetMessage: getMessageTool\n}\n"],"mappings":"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","names":["randomUUID","randomUUID","createPublicClient","http","base","base","createPublicClient","http","z","z"]}
@@ -1,7 +1,8 @@
1
- import { b as Plugin, f as PluginContext } from '../agent-BxbcW5UC.cjs';
1
+ import { b as Plugin, c as PluginContext } from '../agent-MbcG6CoX.cjs';
2
2
  import 'ai';
3
3
  import 'zod';
4
4
  import '@hybrd/xmtp';
5
+ import '../tool-CoVdD8Fb.cjs';
5
6
  import 'hono';
6
7
 
7
8
  declare function createPonderBlockchainForwarder(options?: {
@@ -1,7 +1,8 @@
1
- import { b as Plugin, f as PluginContext } from '../agent-BxbcW5UC.js';
1
+ import { b as Plugin, c as PluginContext } from '../agent-6fncjbIG.js';
2
2
  import 'ai';
3
3
  import 'zod';
4
4
  import '@hybrd/xmtp';
5
+ import '../tool-CoVdD8Fb.js';
5
6
  import 'hono';
6
7
 
7
8
  declare function createPonderBlockchainForwarder(options?: {
@@ -0,0 +1,73 @@
1
+ import { UIMessage } from 'ai';
2
+ import { z } from 'zod';
3
+ import { XmtpConversation, XmtpMessage, XmtpSender, XmtpSubjects, XmtpServiceClient } from '@hybrd/xmtp';
4
+
5
+ interface BaseRuntime extends Record<string, unknown> {
6
+ conversation: XmtpConversation;
7
+ message: XmtpMessage;
8
+ parentMessage?: XmtpMessage;
9
+ rootMessage: XmtpMessage;
10
+ sender: XmtpSender;
11
+ subjects: XmtpSubjects;
12
+ xmtpClient: XmtpServiceClient;
13
+ }
14
+ type AgentRuntime = BaseRuntime & {
15
+ chatId?: string;
16
+ messages: Array<UIMessage>;
17
+ };
18
+ interface XmtpCredentials {
19
+ inboxId: string;
20
+ xmtpServiceUrl: string;
21
+ xmtpServiceToken: string;
22
+ }
23
+
24
+ type DefaultRuntimeExtension = Record<string, never>;
25
+ /**
26
+ * Configuration interface for creating custom tools that integrate with AI SDK.
27
+ */
28
+ interface ToolConfig<TInput extends z.ZodTypeAny = z.ZodTypeAny, TOutput extends z.ZodTypeAny = z.ZodTypeAny, TRuntimeExtension = DefaultRuntimeExtension> {
29
+ /** Unique identifier for the tool */
30
+ id: string;
31
+ /** Human-readable description of what the tool does */
32
+ description: string;
33
+ /** Zod schema for validating tool input */
34
+ inputSchema: TInput;
35
+ /** Optional Zod schema for validating tool output */
36
+ outputSchema?: TOutput;
37
+ /** Function that executes the tool's logic */
38
+ execute: (args: {
39
+ input: z.infer<TInput>;
40
+ runtime: AgentRuntime & TRuntimeExtension;
41
+ messages: UIMessage[];
42
+ }) => Promise<z.infer<TOutput>>;
43
+ }
44
+ /**
45
+ * Internal tool interface used throughout the agent framework.
46
+ * Similar to ToolConfig but without the ID field, used after tool creation.
47
+ */
48
+ interface Tool<TInput extends z.ZodTypeAny = z.ZodTypeAny, TOutput extends z.ZodTypeAny = z.ZodTypeAny, TRuntimeExtension = DefaultRuntimeExtension> {
49
+ /** Human-readable description of what the tool does */
50
+ description: string;
51
+ /** Zod schema for validating tool input */
52
+ inputSchema: TInput;
53
+ /** Optional Zod schema for validating tool output */
54
+ outputSchema?: TOutput;
55
+ /** Function that executes the tool's logic */
56
+ execute: (args: {
57
+ input: z.infer<TInput>;
58
+ runtime: AgentRuntime & TRuntimeExtension;
59
+ messages: UIMessage[];
60
+ }) => Promise<z.infer<TOutput>>;
61
+ }
62
+ /**
63
+ * Factory function to create tools with custom runtime extensions.
64
+ * Provides proper type inference for input/output schemas and runtime extensions.
65
+ */
66
+ declare function toolFactory<TRuntimeExtension = DefaultRuntimeExtension>(): <TInput extends z.ZodTypeAny, TOutput extends z.ZodTypeAny = z.ZodTypeAny>(config: ToolConfig<TInput, TOutput, TRuntimeExtension>) => Tool<TInput, TOutput, TRuntimeExtension>;
67
+ /**
68
+ * Default tool factory with no runtime extensions.
69
+ * Type-safe at creation time with proper schema inference.
70
+ */
71
+ declare const createTool: <TInput extends z.ZodTypeAny, TOutput extends z.ZodTypeAny = z.ZodTypeAny>(config: ToolConfig<TInput, TOutput, DefaultRuntimeExtension>) => Tool<TInput, TOutput, DefaultRuntimeExtension>;
72
+
73
+ export { type AgentRuntime as A, type BaseRuntime as B, type Tool as T, type XmtpCredentials as X, type ToolConfig as a, createTool as c, toolFactory as t };
@@ -0,0 +1,73 @@
1
+ import { UIMessage } from 'ai';
2
+ import { z } from 'zod';
3
+ import { XmtpConversation, XmtpMessage, XmtpSender, XmtpSubjects, XmtpServiceClient } from '@hybrd/xmtp';
4
+
5
+ interface BaseRuntime extends Record<string, unknown> {
6
+ conversation: XmtpConversation;
7
+ message: XmtpMessage;
8
+ parentMessage?: XmtpMessage;
9
+ rootMessage: XmtpMessage;
10
+ sender: XmtpSender;
11
+ subjects: XmtpSubjects;
12
+ xmtpClient: XmtpServiceClient;
13
+ }
14
+ type AgentRuntime = BaseRuntime & {
15
+ chatId?: string;
16
+ messages: Array<UIMessage>;
17
+ };
18
+ interface XmtpCredentials {
19
+ inboxId: string;
20
+ xmtpServiceUrl: string;
21
+ xmtpServiceToken: string;
22
+ }
23
+
24
+ type DefaultRuntimeExtension = Record<string, never>;
25
+ /**
26
+ * Configuration interface for creating custom tools that integrate with AI SDK.
27
+ */
28
+ interface ToolConfig<TInput extends z.ZodTypeAny = z.ZodTypeAny, TOutput extends z.ZodTypeAny = z.ZodTypeAny, TRuntimeExtension = DefaultRuntimeExtension> {
29
+ /** Unique identifier for the tool */
30
+ id: string;
31
+ /** Human-readable description of what the tool does */
32
+ description: string;
33
+ /** Zod schema for validating tool input */
34
+ inputSchema: TInput;
35
+ /** Optional Zod schema for validating tool output */
36
+ outputSchema?: TOutput;
37
+ /** Function that executes the tool's logic */
38
+ execute: (args: {
39
+ input: z.infer<TInput>;
40
+ runtime: AgentRuntime & TRuntimeExtension;
41
+ messages: UIMessage[];
42
+ }) => Promise<z.infer<TOutput>>;
43
+ }
44
+ /**
45
+ * Internal tool interface used throughout the agent framework.
46
+ * Similar to ToolConfig but without the ID field, used after tool creation.
47
+ */
48
+ interface Tool<TInput extends z.ZodTypeAny = z.ZodTypeAny, TOutput extends z.ZodTypeAny = z.ZodTypeAny, TRuntimeExtension = DefaultRuntimeExtension> {
49
+ /** Human-readable description of what the tool does */
50
+ description: string;
51
+ /** Zod schema for validating tool input */
52
+ inputSchema: TInput;
53
+ /** Optional Zod schema for validating tool output */
54
+ outputSchema?: TOutput;
55
+ /** Function that executes the tool's logic */
56
+ execute: (args: {
57
+ input: z.infer<TInput>;
58
+ runtime: AgentRuntime & TRuntimeExtension;
59
+ messages: UIMessage[];
60
+ }) => Promise<z.infer<TOutput>>;
61
+ }
62
+ /**
63
+ * Factory function to create tools with custom runtime extensions.
64
+ * Provides proper type inference for input/output schemas and runtime extensions.
65
+ */
66
+ declare function toolFactory<TRuntimeExtension = DefaultRuntimeExtension>(): <TInput extends z.ZodTypeAny, TOutput extends z.ZodTypeAny = z.ZodTypeAny>(config: ToolConfig<TInput, TOutput, TRuntimeExtension>) => Tool<TInput, TOutput, TRuntimeExtension>;
67
+ /**
68
+ * Default tool factory with no runtime extensions.
69
+ * Type-safe at creation time with proper schema inference.
70
+ */
71
+ declare const createTool: <TInput extends z.ZodTypeAny, TOutput extends z.ZodTypeAny = z.ZodTypeAny>(config: ToolConfig<TInput, TOutput, DefaultRuntimeExtension>) => Tool<TInput, TOutput, DefaultRuntimeExtension>;
72
+
73
+ export { type AgentRuntime as A, type BaseRuntime as B, type Tool as T, type XmtpCredentials as X, type ToolConfig as a, createTool as c, toolFactory as t };