@agentxv2/sdk 0.3.1 → 0.5.0

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/react/useAgentRunner.ts","../../src/core/crypto.ts","../../src/registry/ipfs-fetcher.ts","../../src/core/types.ts","../../src/agent/agent-runner.ts","../../src/config/config.ts"],"sourcesContent":["// ---------------------------------------------------------------------------\n// @agentx/sdk — useAgentRunner React Hook\n// ---------------------------------------------------------------------------\n// Wraps AgentRunner.useAgent() for React + wagmi integration.\n//\n// const { ctx, isLoading, error } = useAgentRunner(agentId)\n// // ctx.prompt → inject into LLM\n// // ctx.skills → RunnableSkill[] with execute()\n// // ctx.mcp → MCP connection info\n// ---------------------------------------------------------------------------\n\n'use client'\n\nimport { useState, useEffect, useRef } from 'react'\nimport { usePublicClient, useWalletClient } from 'wagmi'\nimport type { Address } from 'viem'\n\nimport { AgentRunner } from '../agent/agent-runner'\nimport type { AgentRunContext, OnChainReader } from '../agent/agent-runner'\nimport { IPFSFetcher } from '../registry/ipfs-fetcher'\nimport { KNOWN_CHAINS } from '../config/config'\nimport type { ChainConfig } from '../config/config'\n\n// ── IdentityRegistry ABI (minimal — only what useAgent needs) ──────────────\n\nconst IDENTITY_REGISTRY_ABI = [\n // getAgentMetadata returns MetadataEntry[] with key+value strings\n {\n name: 'getAgentMetadata',\n type: 'function',\n stateMutability: 'view',\n inputs: [{ name: 'agentId', type: 'uint256' }],\n outputs: [\n {\n name: '',\n type: 'tuple[]',\n components: [\n { name: 'key', type: 'string' },\n { name: 'value', type: 'bytes' },\n ],\n },\n ],\n },\n] as const\n\n// ── SubscriptionManager ABI (minimal) ─────────────────────────────────────\n\nconst SUBSCRIPTION_MANAGER_ABI = [\n {\n name: 'hasActiveSubscription',\n type: 'function',\n stateMutability: 'view',\n inputs: [\n { name: 'subscriber', type: 'address' },\n { name: 'agentId', type: 'uint256' },\n ],\n outputs: [{ name: '', type: 'bool' }],\n },\n] as const\n\n// ── Hook Config ────────────────────────────────────────────────────────────\n\nexport interface UseAgentRunnerConfig {\n agentId: number\n chainConfig?: ChainConfig\n ipfsGateways?: string[]\n}\n\nexport interface UseAgentRunnerResult {\n ctx: AgentRunContext | null\n isLoading: boolean\n error: Error | null\n /** Re-trigger the load (e.g. after connecting wallet or subscribing) */\n refetch: () => void\n}\n\n// ── OnChainReader Implementation (viem) ────────────────────────────────────\n\nclass ViemOnChainReader implements OnChainReader {\n constructor(\n private publicClient: ReturnType<typeof usePublicClient>,\n private chainConfig: ChainConfig\n ) {}\n\n async getTokenURI(_agentId: number): Promise<string> {\n // tokenURI is standard ERC-721 metadata — not needed for our flow\n // Metadata is fetched via getAgentMetadata\n return ''\n }\n\n async getAttributes(agentId: number): Promise<Record<string, string>> {\n if (!this.publicClient) throw new Error('Public client not available')\n\n const entries = (await this.publicClient.readContract({\n address: this.chainConfig.contracts.identityRegistry,\n abi: IDENTITY_REGISTRY_ABI,\n functionName: 'getAgentMetadata',\n args: [BigInt(agentId)],\n })) as { key: string; value: string }[]\n\n const attrs: Record<string, string> = {}\n for (const entry of entries) {\n // value is bytes — convert to string\n const hexStr = entry.value\n if (hexStr && hexStr !== '0x') {\n attrs[entry.key] = hexToStringUTF8(hexStr)\n } else {\n attrs[entry.key] = ''\n }\n }\n return attrs\n }\n\n async hasActiveSubscription(address: string, agentId: number): Promise<boolean> {\n if (!this.publicClient) return false\n\n try {\n return (await this.publicClient.readContract({\n address: this.chainConfig.contracts.subscriptionManager,\n abi: SUBSCRIPTION_MANAGER_ABI,\n functionName: 'hasActiveSubscription',\n args: [address as Address, BigInt(agentId)],\n })) as boolean\n } catch {\n return false\n }\n }\n}\n\n// ── Helpers ────────────────────────────────────────────────────────────────\n\nfunction hexToStringUTF8(hex: string): string {\n if (!hex.startsWith('0x')) return hex\n const hexClean = hex.slice(2)\n if (hexClean.length === 0) return ''\n try {\n const bytes = new Uint8Array(hexClean.length / 2)\n for (let i = 0; i < bytes.length; i++) {\n bytes[i] = parseInt(hexClean.substring(i * 2, i * 2 + 2), 16)\n }\n return new TextDecoder().decode(bytes)\n } catch {\n return hex\n }\n}\n\n// ── Hook ───────────────────────────────────────────────────────────────────\n\nexport function useAgentRunner(config: UseAgentRunnerConfig): UseAgentRunnerResult {\n const { agentId, chainConfig: chainConfigOverride, ipfsGateways } = config\n\n const publicClient = usePublicClient()\n const { data: walletClient } = useWalletClient()\n\n const [ctx, setCtx] = useState<AgentRunContext | null>(null)\n const [isLoading, setIsLoading] = useState(false)\n const [error, setError] = useState<Error | null>(null)\n const [refetchKey, setRefetchKey] = useState(0)\n\n const runnerRef = useRef<AgentRunner | null>(null)\n const mountedRef = useRef(true)\n\n useEffect(() => {\n mountedRef.current = true\n return () => {\n mountedRef.current = false\n }\n }, [])\n\n useEffect(() => {\n if (!publicClient || !walletClient) {\n setError(new Error('Wallet not connected'))\n return\n }\n\n const chainConfig =\n chainConfigOverride ?? (publicClient.chain?.id ? KNOWN_CHAINS[publicClient.chain.id] : undefined)\n\n if (!chainConfig) {\n setError(new Error(`Chain ${publicClient.chain?.id} not supported`))\n return\n }\n\n // Create OnChainReader\n const reader = new ViemOnChainReader(publicClient, chainConfig)\n\n // WalletSigner from wagmi\n const signer = {\n async signMessage(message: string): Promise<string> {\n if (!walletClient.account) throw new Error('Wallet not connected')\n return walletClient.signMessage({ account: walletClient.account, message })\n },\n async getAddress(): Promise<string> {\n if (!walletClient.account) throw new Error('Wallet not connected')\n return walletClient.account.address\n },\n async getPrivateKey(): Promise<string> {\n // wagmi walletClient doesn't expose private key\n // ECIES decryption requires private key — must be injected from wallet provider\n throw new Error(\n 'Private key not available via wagmi. ' +\n 'Use window.ethereum.request({ method: \"eth_private_key\" }) or inject getPrivateKey via custom WalletSigner.'\n )\n },\n }\n\n // IPFS Fetcher\n const ipfsFetcher = new IPFSFetcher({\n fallbackGateways: ipfsGateways ?? chainConfig.ipfsGateways ?? [\n 'gateway.pinata.cloud',\n 'dweb.link',\n 'cf-ipfs.com',\n ],\n })\n\n runnerRef.current = new AgentRunner({\n reader,\n wallet: signer,\n ipfsFetcher,\n })\n\n setIsLoading(true)\n setError(null)\n\n runnerRef.current\n .useAgent(agentId)\n .then(result => {\n if (mountedRef.current) {\n setCtx(result)\n setIsLoading(false)\n }\n })\n .catch(err => {\n if (mountedRef.current) {\n setError(err instanceof Error ? err : new Error(String(err)))\n setIsLoading(false)\n }\n })\n\n return () => {\n mountedRef.current = false\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [agentId, publicClient?.chain?.id, publicClient, walletClient, refetchKey])\n\n const refetch = () => setRefetchKey(k => k + 1)\n\n return { ctx, isLoading, error, refetch }\n}\n","// ---------------------------------------------------------------------------\n// @agentx/sdk — Crypto Engine\n// ---------------------------------------------------------------------------\n// AES-256-GCM for content encryption (NIST standard, same wire format as\n// aihunter-saas for interop). ECIES (secp256k1) for key wrapping.\n//\n// Wire format (AES-256-GCM):\n// base64( IV[12] || ciphertext || authTag[16] )\n//\n// ECIES wire format (compatible with eciesjs):\n// hex( ephemeralPub[33] || IV[16] || ciphertext || MAC[32] )\n//\n// Pure JS — works in browser, Node, edge. No native deps except @noble/*.\n// ---------------------------------------------------------------------------\n\nimport { gcm } from '@noble/ciphers/aes.js'\nimport { secp256k1 } from '@noble/curves/secp256k1.js'\nimport { sha256 } from '@noble/hashes/sha2.js'\nimport { hkdf } from '@noble/hashes/hkdf.js'\nimport { hmac } from '@noble/hashes/hmac.js'\nimport { bytesToHex, hexToBytes } from '@noble/ciphers/utils.js'\n\n// ── randomBytes implementation (cross-runtime: browser / Node) ────────────\n\nexport function randomBytes(length: number): Uint8Array {\n // browser: crypto.getRandomValues\n if (typeof crypto !== 'undefined' && crypto.getRandomValues) {\n const buf = new Uint8Array(length)\n crypto.getRandomValues(buf)\n return buf\n }\n // Node: crypto.randomBytes\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const nodeCrypto = require('crypto')\n return new Uint8Array(nodeCrypto.randomBytes(length))\n}\n\nimport type { EncryptedPayload, AgentPrivatePayload } from './types'\nimport type { PackResult } from './types'\n\n// ── Re-exports for convenience ─────────────────────────────────────────────\n\nexport { bytesToHex, hexToBytes }\n\n// ── Constants ──────────────────────────────────────────────────────────────\n\nconst AES_KEY_SIZE = 32\nconst IV_SIZE = 12 // GCM recommended\nconst TAG_SIZE = 16 // GCM auth tag\n\n// ── Base64 helpers (cross-runtime) ─────────────────────────────────────────\n\nfunction toBase64(bytes: Uint8Array): string {\n // Works in browser (btoa + binary) and Node (Buffer)\n if (typeof Buffer !== 'undefined') return Buffer.from(bytes).toString('base64')\n let binary = ''\n for (let i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i]!)\n return btoa(binary)\n}\n\nfunction fromBase64(b64: string): Uint8Array {\n if (typeof Buffer !== 'undefined') return new Uint8Array(Buffer.from(b64, 'base64'))\n const binary = atob(b64)\n const bytes = new Uint8Array(binary.length)\n for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i)\n return bytes\n}\n\n// ── AES-256-GCM ────────────────────────────────────────────────────────────\n\n/**\n * Encrypt with AES-256-GCM.\n * Wire format (same as aihunter-saas): base64( IV[12] || ciphertext || authTag[16] )\n */\nexport function aesEncrypt(plaintext: string, keyHex: string): string {\n const key = hexToBytes(keyHex)\n const iv = randomBytes(IV_SIZE)\n const plainBytes = new TextEncoder().encode(plaintext)\n\n const cipher = gcm(key, iv)\n const encrypted = cipher.encrypt(plainBytes)\n // noble gcm.encrypt returns: ciphertext || authTag(16)\n const ciphertext = encrypted.subarray(0, -TAG_SIZE)\n const authTag = encrypted.subarray(-TAG_SIZE)\n\n // Pack: IV || ciphertext || authTag\n const combined = new Uint8Array(IV_SIZE + ciphertext.length + TAG_SIZE)\n combined.set(iv, 0)\n combined.set(ciphertext, IV_SIZE)\n combined.set(authTag, IV_SIZE + ciphertext.length)\n\n return toBase64(combined)\n}\n\n/**\n * Decrypt AES-256-GCM (same wire format as aihunter-saas).\n */\nexport function aesDecrypt(encryptedBase64: string, keyHex: string): string {\n const key = hexToBytes(keyHex)\n const combined = fromBase64(encryptedBase64)\n\n const iv = combined.subarray(0, IV_SIZE)\n const ciphertext = combined.subarray(IV_SIZE, -TAG_SIZE)\n const authTag = combined.subarray(-TAG_SIZE)\n\n const cipher = gcm(key, iv)\n // noble decrypt expects: ciphertext || authTag\n const ciphertextWithTag = new Uint8Array(ciphertext.length + TAG_SIZE)\n ciphertextWithTag.set(ciphertext, 0)\n ciphertextWithTag.set(authTag, ciphertext.length)\n\n const decrypted = cipher.decrypt(ciphertextWithTag)\n return new TextDecoder().decode(decrypted)\n}\n\n/**\n * Generate a cryptographically random AES-256 key (hex, 64 chars).\n */\nexport function generateAesKey(): string {\n return bytesToHex(randomBytes(AES_KEY_SIZE))\n}\n\n// ── ECIES (secp256k1) ──────────────────────────────────────────────────────\n//\n// eciesjs-compatible wire format:\n// ephemeralPub(33B compressed) || IV(16B) || ciphertext || MAC(32B)\n// Encoding: hex\n//\n// HKDF(SHA-256) derives AES key + HMAC key from ECDH shared secret.\n// ---------------------------------------------------------------------------\n\nfunction eciesEncode(\n ephemeralPub: Uint8Array,\n iv: Uint8Array,\n ciphertext: Uint8Array,\n mac: Uint8Array\n): string {\n const out = new Uint8Array(33 + 16 + ciphertext.length + 32)\n out.set(ephemeralPub, 0)\n out.set(iv, 33)\n out.set(ciphertext, 33 + 16)\n out.set(mac, 33 + 16 + ciphertext.length)\n return bytesToHex(out)\n}\n\nfunction eciesDecode(dataHex: string): {\n ephemeralPub: Uint8Array\n iv: Uint8Array\n ciphertext: Uint8Array\n mac: Uint8Array\n} {\n const d = hexToBytes(dataHex)\n return {\n ephemeralPub: d.subarray(0, 33),\n iv: d.subarray(33, 49),\n ciphertext: d.subarray(49, -32),\n mac: d.subarray(-32),\n }\n}\n\n// Simple AES-256-CTR implementation on top of @noble/ciphers AES core\nfunction aesCtrEncrypt(key: Uint8Array, ctrBytes: Uint8Array, data: Uint8Array): Uint8Array {\n const blockSize = 16\n const cipher = gcm(key, ctrBytes) // GCM internally handles CTR\n // Use noble's CTR approach: encrypt the plaintext directly with the derived stream\n // noble uses AES-CTR internally for GCM; simpler: implement CTR with AES-ECB\n const result = new Uint8Array(data.length)\n const counter = new Uint8Array(blockSize)\n counter.set(ctrBytes)\n for (let i = 0; i < data.length; i += blockSize) {\n const keystream = gcm(key, counter).encrypt(new Uint8Array(blockSize))\n for (let j = 0; j < blockSize && i + j < data.length; j++) {\n result[i + j] = keystream[j]! ^ data[i + j]!\n }\n // Increment counter (big-endian)\n for (let j = blockSize - 1; j >= 0; j--) {\n const val = counter[j]\n if (val !== undefined) {\n counter[j] = (val + 1) & 0xff\n if (counter[j] !== 0) break\n }\n }\n }\n return result\n}\n\n/**\n * Encrypt data with recipient's secp256k1 public key (ECIES).\n *\n * @param dataHex The data to encrypt (hex, e.g. AES key)\n * @param publicKey Recipient's public key (hex, 04-prefixed uncompressed or 02/03 compressed)\n */\nexport function eciesEncrypt(dataHex: string, publicKey: string): string {\n // 1. Ephemeral keypair\n const ephPriv = randomBytes(32)\n const ephPub = secp256k1.getPublicKey(ephPriv, true) // 33B compressed\n\n // 2. Parse recipient public key\n let recipientPub: Uint8Array\n if (publicKey.startsWith('04') && publicKey.length === 130) {\n recipientPub = hexToBytes(publicKey)\n } else if (publicKey.startsWith('02') || publicKey.startsWith('03')) {\n recipientPub = hexToBytes(publicKey)\n } else {\n throw new Error('Invalid public key format: expected hex with 02/03/04 prefix')\n }\n\n // 3. ECDH\n const shared = secp256k1.getSharedSecret(ephPriv, recipientPub)\n const sharedX = shared.subarray(1, 33) // x-coordinate only\n const sharedKey = sha256(sharedX)\n\n // 4. HKDF: encKey(32) || macKey(32)\n const hkdfOut = hkdf(sha256, sharedKey, undefined, undefined, 64)\n const encKey = hkdfOut.subarray(0, 32)\n const macKey = hkdfOut.subarray(32, 64)\n\n // 5. AES-256-CTR encrypt\n const iv = randomBytes(16)\n const plaintext = hexToBytes(dataHex)\n const ciphertext = aesCtrEncrypt(encKey, iv, plaintext)\n\n // 6. HMAC: MAC(ephemeralPub || IV || ciphertext)\n const macInput = new Uint8Array(33 + 16 + ciphertext.length)\n macInput.set(ephPub, 0)\n macInput.set(iv, 33)\n macInput.set(ciphertext, 33 + 16)\n const mac = hmac(sha256, macKey, macInput)\n\n return eciesEncode(ephPub, iv, ciphertext, mac)\n}\n\n/**\n * Decrypt ECIES ciphertext with recipient's secp256k1 private key.\n */\nexport function eciesDecrypt(dataHex: string, privateKey: string): string {\n const { ephemeralPub, iv, ciphertext, mac } = eciesDecode(dataHex)\n\n // 1. ECDH\n const privBytes = hexToBytes(privateKey)\n const shared = secp256k1.getSharedSecret(privBytes, ephemeralPub)\n const sharedX = shared.subarray(1, 33)\n const sharedKey = sha256(sharedX)\n\n // 2. HKDF\n const hkdfOut = hkdf(sha256, sharedKey, undefined, undefined, 64)\n const encKey = hkdfOut.subarray(0, 32)\n const macKey = hkdfOut.subarray(32, 64)\n\n // 3. Verify MAC\n const macInput = new Uint8Array(33 + 16 + ciphertext.length)\n macInput.set(ephemeralPub, 0)\n macInput.set(iv, 33)\n macInput.set(ciphertext, 33 + 16)\n const expectedMac = hmac(sha256, macKey, macInput)\n if (!constantTimeEqual(mac, expectedMac)) {\n throw new Error('ECIES decryption failed: MAC mismatch')\n }\n\n // 4. Decrypt\n const plaintext = aesCtrEncrypt(encKey, iv, ciphertext) // CTR encrypt = decrypt\n return bytesToHex(plaintext)\n}\n\nfunction constantTimeEqual(a: Uint8Array, b: Uint8Array): boolean {\n if (a.length !== b.length) return false\n let diff = 0\n for (let i = 0; i < a.length; i++) diff |= a[i]! ^ b[i]!\n return diff === 0\n}\n\n// ── High-Level: Agent Pack / Unpack ────────────────────────────────────────\n\n/**\n * Encrypt an Agent's private payload with AES-256-GCM.\n */\nexport function encryptPayload(\n payload: AgentPrivatePayload,\n keyHex?: string\n): EncryptedPayload {\n const key = keyHex ?? generateAesKey()\n return {\n encrypted: true,\n algorithm: 'AES-256-GCM',\n data: aesEncrypt(JSON.stringify(payload), key),\n }\n}\n\n/**\n * Decrypt an EncryptedPayload.\n */\nexport function decryptPayload(\n encrypted: EncryptedPayload,\n keyHex: string\n): AgentPrivatePayload {\n if (encrypted.algorithm !== 'AES-256-GCM') {\n throw new Error(`Unsupported algorithm: ${encrypted.algorithm}`)\n }\n return JSON.parse(aesDecrypt(encrypted.data, keyHex)) as AgentPrivatePayload\n}\n\n/**\n * Pack an AgentPayload for publishing.\n * 1. Split public/private\n * 2. AES-256-GCM encrypt private part\n * 3. ECIES wrap AES key with creator's public key\n */\nexport function packAgentForPublish(\n agent: import('./types').AgentPayload,\n publicKey: string,\n aesKeyHex?: string\n): PackResult {\n const key = aesKeyHex ?? generateAesKey()\n\n const eciesEncryptedKeyHex = eciesEncrypt(key, publicKey)\n\n return {\n encryptedCid: '', // filled after IPFS upload\n publicCid: '', // filled after IPFS upload\n aesKeyHex: key,\n eciesEncryptedKeyHex,\n }\n}\n\n/**\n * Unpack an Agent:\n * 1. ECIES decrypt the AES key (private key)\n * 2. AES-256-GCM decrypt the payload\n */\nexport function unpackAgent(\n encryptedPayload: EncryptedPayload,\n eciesEncryptedKey: string,\n privateKey: string\n): AgentPrivatePayload {\n const aesKeyHex = eciesDecrypt(eciesEncryptedKey, privateKey)\n return decryptPayload(encryptedPayload, aesKeyHex)\n}\n\n// ── Key Pair Utilities ─────────────────────────────────────────────────────\n\n/**\n * Generate a secp256k1 keypair compatible with Ethereum wallets.\n */\nexport function generateKeyPair(): { privateKey: string; publicKey: string } {\n const priv = randomBytes(32)\n const pub = secp256k1.getPublicKey(priv, false) // uncompressed 04-prefixed\n return { privateKey: bytesToHex(priv), publicKey: bytesToHex(pub) }\n}\n\n/**\n * Derive public key from private key (hex).\n */\nexport function getPublicKey(privateKey: string): string {\n return bytesToHex(secp256k1.getPublicKey(hexToBytes(privateKey), false))\n}\n","// ---------------------------------------------------------------------------\n// @agentx/sdk — IPFS Fetcher\n// ---------------------------------------------------------------------------\n// Multi-gateway IPFS fetcher with in-memory cache, deduplication, and\n// automatic fallback. Compatible with the EncryptedPayload wire format.\n// ---------------------------------------------------------------------------\n\nimport type { EncryptedPayload } from '../core/types'\n\n// ── Types ───────────────────────────────────────────────────────────────────\n\nexport interface IPFSFetcherConfig {\n /** Primary IPFS gateway (default: ipfs.io) */\n gateway?: string\n /** Fallback gateways in order of preference */\n fallbackGateways?: string[]\n /** Request timeout in ms (default: 10_000) */\n timeoutMs?: number\n /** Max cached entries (LRU-like eviction, default: 200) */\n maxCache?: number\n}\n\ntype CacheEntry<T> = {\n data: T\n timestamp: number\n}\n\n// ── Implementation ─────────────────────────────────────────────────────────\n\nexport class IPFSFetcher {\n private gateway: string\n private fallbackGateways: string[]\n private timeoutMs: number\n\n private cache = new Map<string, CacheEntry<unknown>>()\n private maxCache: number\n private pending = new Map<string, Promise<unknown>>()\n private failed = new Set<string>()\n\n constructor(config: IPFSFetcherConfig = {}) {\n this.gateway = config.gateway ?? 'ipfs.io'\n this.fallbackGateways = config.fallbackGateways ?? [\n 'gateway.pinata.cloud',\n 'dweb.link',\n 'cf-ipfs.com',\n ]\n this.timeoutMs = config.timeoutMs ?? 10_000\n this.maxCache = config.maxCache ?? 200\n }\n\n // ── Public API ──────────────────────────────────────────────────────────\n\n /** Fetch JSON from a single IPFS CID. */\n async fetchJSON<T = unknown>(cid: string): Promise<T> {\n const cached = this.cache.get(cid)\n if (cached) return cached.data as T\n\n if (this.failed.has(cid)) throw new Error(`CID ${cid} previously failed`)\n\n const pending = this.pending.get(cid)\n if (pending) return pending as Promise<T>\n\n const promise = this._doFetch<T>(cid)\n this.pending.set(cid, promise)\n\n try {\n const data = await promise\n this._cacheSet(cid, data)\n return data\n } catch (e) {\n this.failed.add(cid)\n throw e\n } finally {\n this.pending.delete(cid)\n }\n }\n\n /** Fetch encrypted agent payload (validates algorithm). */\n async fetchEncryptedPayload(cid: string): Promise<EncryptedPayload> {\n const raw = await this.fetchJSON<Record<string, unknown>>(cid)\n if (!raw.encrypted || raw.algorithm !== 'AES-256-GCM' || typeof raw.data !== 'string') {\n throw new Error(`Invalid EncryptedPayload at CID ${cid}`)\n }\n return raw as unknown as EncryptedPayload\n }\n\n /** Batch fetch multiple CIDs with concurrency control. */\n async fetchBatch<T = unknown>(cids: string[], concurrency = 5): Promise<Map<string, T>> {\n const results = new Map<string, T>()\n const unique = [...new Set(cids)].filter(c => this.isValidCID(c))\n\n for (let i = 0; i < unique.length; i += concurrency) {\n const batch = unique.slice(i, i + concurrency)\n const settled = await Promise.allSettled(\n batch.map(cid => this.fetchJSON<T>(cid))\n )\n settled.forEach((r, j) => {\n if (r.status === 'fulfilled') results.set(batch[j]!, r.value)\n })\n if (i + concurrency < unique.length) {\n await new Promise(r => setTimeout(r, 200))\n }\n }\n return results\n }\n\n /** Check if a string looks like a valid IPFS CID. */\n isValidCID(cid: string): boolean {\n return /^(Qm[1-9A-HJ-NP-Za-km-z]{44,}|b[a-z2-7]{58,}|[A-Za-z0-9+/]{46,})$/.test(cid)\n }\n\n /** Clear cache (optionally for a specific CID). */\n clearCache(cid?: string): void {\n if (cid) {\n this.cache.delete(cid)\n } else {\n this.cache.clear()\n }\n this.failed.clear()\n }\n\n /** Number of cached entries. */\n get cacheSize(): number {\n return this.cache.size\n }\n\n // ── Internal ─────────────────────────────────────────────────────────────\n\n private async _doFetch<T>(cid: string): Promise<T> {\n if (!this.isValidCID(cid)) throw new Error(`Invalid CID: ${cid}`)\n\n // Try primary gateway\n try {\n return await this._fetchFrom(cid, this.gateway, this.timeoutMs)\n } catch {\n // fall through to alternatives\n }\n\n // Try fallback gateways\n for (const gw of this.fallbackGateways) {\n try {\n return await this._fetchFrom(cid, gw, this.timeoutMs)\n } catch {\n // try next\n }\n }\n\n throw new Error(`All IPFS gateways failed for CID ${cid}`)\n }\n\n private async _fetchFrom<T>(cid: string, gateway: string, timeoutMs: number): Promise<T> {\n const url = `https://${gateway}/ipfs/${cid}`\n const res = await fetch(url, {\n headers: { Accept: 'application/json' },\n signal: AbortSignal.timeout(timeoutMs),\n })\n if (!res.ok) throw new Error(`HTTP ${res.status}`)\n return (await res.json()) as T\n }\n\n private _cacheSet(cid: string, data: unknown): void {\n this.cache.set(cid, { data, timestamp: Date.now() })\n // Simple LRU-like eviction\n if (this.cache.size > this.maxCache) {\n const oldest = [...this.cache.entries()].sort(\n (a, b) => a[1].timestamp - b[1].timestamp\n )[0]\n if (oldest) this.cache.delete(oldest[0])\n }\n }\n}\n\n/** Singleton-friendly default instance. */\nexport const defaultIPFSFetcher = new IPFSFetcher()\n","// ---------------------------------------------------------------------------\n// @agentx/sdk — Core Type Definitions\n// ---------------------------------------------------------------------------\n// Agent = Prompt + Skills[] + MCP\n// All crypto-related \"wire\" fields (encryptedPayloadCid, eciesEncryptedKey)\n// live in IPFS metadata attributes → existing ERC8004 contracts are unchanged.\n// ---------------------------------------------------------------------------\n\n// ── JSON Schema (MCP standard subset) ──────────────────────────────────────\n\nexport interface JSONSchema {\n type: 'object' | 'array' | 'string' | 'number' | 'boolean' | 'integer' | 'null'\n properties?: Record<string, JSONSchemaProperty>\n required?: string[]\n description?: string\n items?: JSONSchema\n enum?: (string | number | boolean | null)[]\n}\n\nexport interface JSONSchemaProperty {\n type?: JSONSchema['type'] | JSONSchema['type'][]\n description?: string\n properties?: Record<string, JSONSchemaProperty>\n required?: string[]\n items?: JSONSchema\n enum?: (string | number | boolean | null)[]\n format?: string\n default?: unknown\n}\n\n// ── Skill Definition ───────────────────────────────────────────────────────\n\n/**\n * A single skill module that an Agent exposes.\n * `inputSchema` and `outputSchema` follow MCP Tool JSON Schema conventions.\n */\nexport interface SkillDef {\n /** Unique skill name (e.g. \"solidity_audit\") */\n name: string\n /** Human-readable description shown in the marketplace */\n description: string\n /** Semantic version of this skill */\n version: string\n /** JSON Schema for the tool's input parameters */\n inputSchema: JSONSchema\n /** JSON Schema for the tool's output return value */\n outputSchema?: JSONSchema\n /**\n * Execution mode.\n * - undefined / \"open\": Source is in the encrypted payload, runs locally.\n * - { type: \"mcp\", toolName: \"...\" }: Source lives on the publisher's\n * MCP server. Subscriber only gets Schema + remote execution endpoint.\n * MCP server verifies on-chain subscription on every call.\n * - { type: \"a2a\", targetAgentId: 42 }: Delegates to another AgentX Agent.\n * The caller's AgentRunner loads + decrypts the target Agent, injects\n * its prompt into the LLM context, and exposes its skills as callable\n * tools. This is the core Agent Composition primitive.\n */\n execution?: SkillExecutionRemote | A2ASkillExecution\n}\n\n/** Where the skill code actually runs. */\nexport type SkillExecutionMode = 'open' | 'mcp' | 'a2a'\n\nexport interface SkillExecutionRemote {\n type: 'mcp'\n /** MCP tool name on the publisher's server (e.g. \"run_strategy_abc123\") */\n toolName: string\n /** Optional: explicit MCP endpoint override */\n endpoint?: string\n}\n\n/**\n * A2A Skill Execution — delegate to another AgentX Agent.\n *\n * Example: A \"trading\" Agent has a skill:\n * execution: { type: \"a2a\", targetAgentId: 42 }\n * → When LLM calls this skill, AgentRunner loads Agent #42,\n * decrypts its prompt+skills, and the sub-Agent runs in the\n * same LLM conversation with its own system prompt.\n */\nexport interface A2ASkillExecution {\n type: 'a2a'\n /** On-chain Agent ID to delegate to */\n targetAgentId: number\n /** Optional: restrict which of the target Agent's skills are exposed */\n skillFilter?: string[]\n /** Optional: custom system prompt override for the sub-Agent */\n promptOverride?: string\n}\n\n// ── MCP Connection ─────────────────────────────────────────────────────────\n\nexport type McpTransport = 'http' | 'sse' | 'stdio'\n\nexport interface McpConnection {\n /** Transport type */\n type: McpTransport\n /** MCP server URL (required for http/sse) */\n url?: string\n /** Optional: limit which tools the Agent exposes to users */\n toolFilter?: string[]\n /** Optional: MCP server authentication header / key */\n authHeader?: string\n}\n\n// ── Pricing ────────────────────────────────────────────────────────────────\n\nexport type PricingType = 'subscription' | 'pay_per_use' | 'free'\n\nexport interface AgentPricing {\n type: PricingType\n /** Amount in native unit (e.g. \"0.01\" for 0.01 ETH) */\n amount: string\n /** ERC20 token address, or empty for native currency */\n currency: string\n /** Billing period for subscriptions (e.g. \"month\", \"year\", \"day\") */\n period?: string\n}\n\n// ── Agent Payload (the core data model) ────────────────────────────────────\n\n/**\n * The complete Agent definition.\n *\n * - Fields above \"--- private payload ---\" are public (IPFS publicPayloadCid).\n * - Fields below are encrypted with AES-256-GCM and stored at encryptedPayloadCid.\n */\nexport interface AgentPayload {\n // ── Public (visible in marketplace, stored at publicPayloadCid) ─────────\n name: string\n description: string\n image?: string\n version: string\n tags: string[]\n capabilities: string[]\n supportedTasks: string[]\n communicationProtocol: 'mcp' | 'a2a'\n authenticationMethod: 'ecdsa'\n pricing: AgentPricing\n\n // ── Private (AES-256-GCM encrypted, stored at encryptedPayloadCid) ──────\n prompt: string\n skills: SkillDef[]\n mcp: McpConnection\n}\n\n/** Subset of AgentPayload that is publicly visible */\nexport type AgentPublicPayload = Omit<\n AgentPayload,\n 'prompt' | 'skills' | 'mcp'\n>\n\n/** Fields that must be encrypted before IPFS upload */\nexport type AgentPrivatePayload = Pick<\n AgentPayload,\n 'prompt' | 'skills' | 'mcp'\n>\n\n// ── Encrypted Payload (IPFS wire format) ───────────────────────────────────\n\nexport interface EncryptedPayload {\n encrypted: true\n algorithm: 'AES-256-GCM'\n /** base64(iv + ciphertext + authTag) */\n data: string\n}\n\n// ── On-Chain Metadata (stored in ERC-721 tokenURI attributes) ─────────────\n\nexport interface OnChainAgentMetadata {\n tokenURI: string\n attributes: {\n name: string\n description: string\n /** CID of the AES-256-GCM encrypted payload on IPFS */\n encryptedPayloadCid: string\n /** ECIES-encrypted AES key (secp256k1, hex string) */\n eciesEncryptedKey: string\n /** CID of the public metadata on IPFS */\n publicPayloadCid: string\n capabilities: string[]\n skills: string[]\n mcpEndpoint: string\n version: string\n tags: string[]\n pricingType: PricingType\n pricingAmount: string\n }\n}\n\n// ── Agent Registry ─────────────────────────────────────────────────────────\n\nexport interface RegisteredAgent {\n /** ERC-721 token ID (= agentId) */\n agentId: number\n /** Owner wallet address */\n owner: string\n /** Creator wallet address */\n creator: string\n /** Full on-chain metadata */\n metadata: OnChainAgentMetadata\n /** Block number where agent was registered */\n registeredAt: number\n /** IPFS CID of the full public payload (resolved from tokenURI) */\n publicPayloadCid: string\n}\n\n// ── Agent Search ───────────────────────────────────────────────────────────\n\nexport interface AgentSearchQuery {\n keyword?: string\n capabilities?: string[]\n tags?: string[]\n pricingType?: PricingType\n maxPrice?: string\n owner?: string\n sortBy?: 'latest' | 'reputation' | 'price_asc' | 'price_desc'\n page?: number\n pageSize?: number\n}\n\nexport interface AgentSearchResult {\n agents: RegisteredAgent[]\n total: number\n page: number\n pageSize: number\n}\n\n// ── Subscription ───────────────────────────────────────────────────────────\n\nexport type SubscriptionStatus = 'active' | 'expired' | 'cancelled' | 'pending'\n\nexport interface AgentSubscription {\n subscriptionId: number\n subscriber: string\n agentId: number\n status: SubscriptionStatus\n startedAt: number\n expiresAt: number\n period: string\n}\n\n// ── A2A Protocol ───────────────────────────────────────────────────────────\n\nexport type A2ATaskStatus = 'created' | 'accepted' | 'in_progress' | 'completed' | 'failed'\n\nexport interface A2AAgentCard {\n agentId: number\n name: string\n capabilities: string[]\n supportedTasks: string[]\n /** MCP endpoint URL for direct agent-to-agent communication */\n endpoint: string\n /** Public key for ECDSA authentication */\n publicKey: string\n}\n\nexport interface A2ATask {\n taskId: number\n /** Agent that created the task */\n creator: string\n /** Target agent to execute the task */\n targetAgentId: number\n /** Task type (must be in target's supportedTasks) */\n taskType: string\n /** JSON input payload */\n input: string\n status: A2ATaskStatus\n result?: string\n createdAt: number\n completedAt?: number\n}\n\n// ── Reputation ─────────────────────────────────────────────────────────────\n\nexport interface AgentReputation {\n agentId: number\n averageRating: number\n totalRatings: number\n reviews: AgentReview[]\n}\n\nexport interface AgentReview {\n reviewer: string\n rating: number // 1-5\n comment: string\n timestamp: number\n}\n\n// ── AgentX Client Configuration ────────────────────────────────────────────\n\nexport interface AgentXConfig {\n /** Chain ID (e.g. 11155111 for Sepolia) */\n chainId: number\n /** RPC endpoint override (uses viem's default if omitted) */\n rpcUrl?: string\n /** Contract addresses for the current chain */\n contracts: AgentXContracts\n /** IPFS gateway URLs (ordered by priority) */\n ipfsGateways: string[]\n /** Default IPFS pinning service */\n pinningService?: 'pinata'\n pinataJwt?: string\n}\n\nexport interface AgentXContracts {\n identityRegistry: `0x${string}`\n subscriptionManager: `0x${string}`\n paymentGateway: `0x${string}`\n a2aProtocolRegistry: `0x${string}`\n reputationRegistry: `0x${string}`\n configurationRegistry: `0x${string}`\n}\n\n// ── Agent Packing / Unpacking Result ───────────────────────────────────────\n\nexport interface PackResult {\n /** CID of AES-256-GCM encrypted payload on IPFS */\n encryptedCid: string\n /** CID of public metadata on IPFS */\n publicCid: string\n /** Raw AES key (hex) — DO NOT share or upload this */\n aesKeyHex: string\n /** ECIES-encrypted AES key (hex), safe to store on-chain */\n eciesEncryptedKeyHex: string\n}\n\nexport interface UnpackResult {\n /** Decrypted AgentPayload */\n agent: AgentPayload\n /** CID where the encrypted payload was fetched from */\n encryptedCid: string\n /** CID of the public metadata */\n publicCid: string\n}\n\n// ── Error Types ────────────────────────────────────────────────────────────\n\nexport enum AgentXErrorCode {\n NOT_SUBSCRIBED = 'NOT_SUBSCRIBED',\n SUBSCRIPTION_EXPIRED = 'SUBSCRIPTION_EXPIRED',\n DECRYPTION_FAILED = 'DECRYPTION_FAILED',\n IPFS_FETCH_FAILED = 'IPFS_FETCH_FAILED',\n AGENT_NOT_FOUND = 'AGENT_NOT_FOUND',\n INVALID_SCHEMA = 'INVALID_SCHEMA',\n TX_FAILED = 'TX_FAILED',\n WALLET_NOT_CONNECTED = 'WALLET_NOT_CONNECTED',\n}\n\nexport class AgentXError extends Error {\n code: AgentXErrorCode\n /** If NOT_SUBSCRIBED, carry enough info for wallet/X402 auto-payment */\n paymentInfo?: SubscriptionRequired\n constructor(code: AgentXErrorCode, message: string) {\n super(message)\n this.code = code\n this.name = 'AgentXError'\n }\n}\n\n/**\n * Structured info for wallet/X402 auto-subscription.\n * Thrown by AgentRunner.useAgent() when the user/Agent has no\n * active subscription.\n */\nexport interface SubscriptionRequired {\n agentId: number\n /** Plan IDs available for this Agent (on-chain query) */\n plans?: { planId: number; price: bigint; period: string; payToken: string; trialDays: number }[]\n}\n","// ---------------------------------------------------------------------------\n// @agentx/sdk — Agent Runner\n// ---------------------------------------------------------------------------\n// The unified entry point for \"using\" an Agent.\n//\n// const runner = new AgentRunner({ reader, wallet })\n// const ctx = await runner.useAgent(42)\n// // ctx.prompt → system prompt for LLM\n// // ctx.skills → [{ name, description, inputSchema, execute }]\n// // ctx.mcp → MCP connection info\n//\n// 对于 Open Skill: 直接本地执行(源码在解密后的 payload 里)\n// 对于 Closed Skill:通过 MCP 远程调用 → 发布者服务器执行 + 校验订阅\n// ---------------------------------------------------------------------------\n\nimport { eciesEncrypt, generateAesKey } from '../core/crypto'\nimport { unpackAgent } from '../core/crypto'\nimport { IPFSFetcher } from '../registry/ipfs-fetcher'\nimport type {\n AgentPayload, AgentPrivatePayload,\n EncryptedPayload, SkillDef,\n PackResult, SubscriptionRequired,\n} from '../core/types'\nimport { AgentXError, AgentXErrorCode } from '../core/types'\n\n// ── Injected Dependencies (viem / wagmi integration) ───────────────────────\n\n/** Minimal on-chain reader interface — implement with viem. */\nexport interface OnChainReader {\n /** Read tokenURI from IdentityRegistry by tokenId. */\n getTokenURI(agentId: number): Promise<string>\n /** Get agent metadata attributes (returned as key-value pairs). */\n getAttributes(agentId: number): Promise<Record<string, string>>\n /** Check if `address` has an active subscription for `agentId`. */\n hasActiveSubscription(address: string, agentId: number): Promise<boolean>\n}\n\n/** Minimal wallet signer interface — implement with wagmi/viem. */\nexport interface WalletSigner {\n /** Sign a message (for authentication to MCP servers). */\n signMessage(message: string): Promise<string>\n /** Get the current wallet address. */\n getAddress(): Promise<string>\n /** Get the wallet's ECDSA private key (required for ECIES decryption). */\n getPrivateKey?(): Promise<string>\n}\n\n// ── Agent Runner Configuration ─────────────────────────────────────────────\n\nexport interface AgentRunnerConfig {\n /** On-chain data reader (injected from viem/wagmi). */\n reader: OnChainReader\n /** Wallet signer (injected from wagmi). */\n wallet: WalletSigner\n /** IPFS fetcher instance (creates default if omitted). */\n ipfsFetcher?: IPFSFetcher\n /** IPFS gateway list (overrides IPFSFetcher defaults). */\n ipfsGateways?: string[]\n}\n\n// ── Run Context (returned by useAgent) ─────────────────────────────────────\n\nexport interface AgentRunContext {\n /** Agent NFT token ID */\n agentId: number\n /** System prompt — inject into LLM conversation */\n prompt: string\n /** All skills with execution metadata */\n skills: RunnableSkill[]\n /** MCP connection info */\n mcp: {\n type: string\n url?: string\n toolFilter?: string[]\n }\n /** Subscription expiry timestamp (0 = unknown) */\n subscriptionExpiry: number\n}\n\nexport interface RunnableSkill {\n name: string\n description: string\n inputSchema: Record<string, unknown>\n outputSchema?: Record<string, unknown>\n /** Execution mode */\n mode: 'open' | 'mcp' | 'a2a'\n /** If mode='a2a', the on-chain Agent ID being delegated to */\n a2aTargetAgentId?: number\n /**\n * Execute this skill with the given input.\n * - Open: runs locally (caller provides implementation)\n * - MCP: POSTs to the publisher's MCP server\n * - A2A: loads target Agent context (prompt+skills) via AgentRunner\n */\n execute(input: Record<string, unknown>): Promise<unknown>\n}\n\n// ── A2A Delegation Result ────────────────────────────────────────────────\n\n/**\n * Standard return type for A2A skill execution.\n * The calling LLM receives the sub-Agent's prompt and skills\n * and can inject them into the conversation.\n */\nexport interface A2ASkillResult {\n /** On-chain Agent ID that was delegated to */\n agentId: number\n /** Sub-Agent's decrypted system prompt */\n prompt: string\n /** Sub-Agent's skills (name + description + schema only, no execute) */\n skills: {\n name: string\n description: string\n inputSchema: Record<string, unknown>\n }[]\n /** The original input passed by the caller */\n callerInput: Record<string, unknown>\n}\n\n// ── Agent Runner ───────────────────────────────────────────────────────────\n\nexport class AgentRunner {\n private reader: OnChainReader\n private wallet: WalletSigner\n private ipfs: IPFSFetcher\n\n constructor(config: AgentRunnerConfig) {\n this.reader = config.reader\n this.wallet = config.wallet\n this.ipfs = config.ipfsFetcher ?? new IPFSFetcher({\n fallbackGateways: config.ipfsGateways ?? [\n 'gateway.pinata.cloud',\n 'dweb.link',\n 'cf-ipfs.com',\n ],\n })\n }\n\n // ── Primary API: useAgent ────────────────────────────────────────────────\n\n /**\n * Load and decrypt an Agent, returning a run context ready to inject\n * into any LLM conversation.\n *\n * Steps:\n * 1. Verify on-chain subscription (frontend check)\n * 2. Fetch metadata → get encryptedPayloadCid + eciesEncryptedKey\n * 3. IPFS fetch encrypted payload\n * 4. ECIES decrypt AES key (using wallet private key)\n * 5. AES-256-GCM decrypt payload → { prompt, skills, mcp }\n * 6. Build RunnableSkill wrappers (Open: local stub, Closed: MCP remote)\n */\n async useAgent(agentId: number): Promise<AgentRunContext> {\n // 1. Subscription check (frontend — MCP server also checks)\n const address = await this.wallet.getAddress()\n const isActive = await this.reader.hasActiveSubscription(address, agentId)\n if (!isActive) {\n const err = new AgentXError(\n AgentXErrorCode.NOT_SUBSCRIBED,\n `No active subscription for Agent #${agentId}. ` +\n `Check error.paymentInfo for auto-subscribe via wallet/X402.`,\n )\n ;(err as AgentXError & { paymentInfo: SubscriptionRequired }).paymentInfo = {\n agentId,\n }\n throw err\n }\n\n // 2. Read on-chain metadata\n const attrs = await this.reader.getAttributes(agentId)\n const encryptedPayloadCid = attrs.encryptedPayloadCid\n const eciesEncryptedKey = attrs.eciesEncryptedKey\n\n if (!encryptedPayloadCid || !eciesEncryptedKey) {\n throw new AgentXError(\n AgentXErrorCode.AGENT_NOT_FOUND,\n `Agent #${agentId} metadata incomplete — missing encryptedPayloadCid or eciesEncryptedKey`\n )\n }\n\n // 3. Fetch encrypted payload from IPFS\n let encryptedPayload: EncryptedPayload\n try {\n encryptedPayload = await this.ipfs.fetchEncryptedPayload(encryptedPayloadCid)\n } catch (e) {\n throw new AgentXError(\n AgentXErrorCode.IPFS_FETCH_FAILED,\n `Failed to fetch encrypted payload for agent #${agentId}: ${e}`\n )\n }\n\n // 4 + 5. ECIES + AES decrypt\n let privatePayload: AgentPrivatePayload\n try {\n const privKey = await this._getPrivateKey()\n privatePayload = unpackAgent(encryptedPayload, eciesEncryptedKey, privKey)\n } catch (e) {\n throw new AgentXError(\n AgentXErrorCode.DECRYPTION_FAILED,\n `Failed to decrypt agent #${agentId}: ${e}`\n )\n }\n\n // 6. Build runnable skills\n const skills = privatePayload.skills.map(s => this._wrapSkill(s))\n\n return {\n agentId,\n prompt: privatePayload.prompt,\n skills,\n mcp: {\n type: privatePayload.mcp.type,\n url: privatePayload.mcp.url,\n toolFilter: privatePayload.mcp.toolFilter,\n },\n subscriptionExpiry: 0,\n }\n }\n\n // ── Publishing ───────────────────────────────────────────────────────────\n\n /**\n * Pack an AgentPayload for publishing (encryption only, no IPFS upload).\n * Caller is responsible for IPFS upload and on-chain registration.\n */\n packForPublish(payload: AgentPayload, publicKey: string): PackResult {\n const key = generateAesKey()\n return {\n encryptedCid: '',\n publicCid: '',\n aesKeyHex: key,\n eciesEncryptedKeyHex: eciesEncrypt(key, publicKey),\n }\n }\n\n // ── Internals ────────────────────────────────────────────────────────────\n\n /** Wrap a SkillDef into a RunnableSkill with execute(). */\n private _wrapSkill(skill: SkillDef): RunnableSkill {\n let mode: RunnableSkill['mode'] = 'open'\n let executeFn: (input: Record<string, unknown>) => Promise<unknown>\n\n if (skill.execution) {\n if (skill.execution.type === 'mcp') {\n mode = 'mcp'\n const endpoint = skill.execution.endpoint ?? ''\n const toolName = skill.execution.toolName ?? skill.name\n executeFn = async (input: Record<string, unknown>) => {\n return this._executeMCPTool(endpoint, toolName, input)\n }\n } else if (skill.execution.type === 'a2a') {\n mode = 'a2a'\n executeFn = async (input: Record<string, unknown>) => {\n return this._executeA2ASkill(skill, input)\n }\n } else {\n throw new AgentXError(\n AgentXErrorCode.INVALID_SCHEMA,\n `Unknown execution type \"${(skill.execution as Record<string,string>).type}\" for skill \"${skill.name}\"`\n )\n }\n } else {\n executeFn = async () => {\n throw new AgentXError(\n AgentXErrorCode.INVALID_SCHEMA,\n `Open skill \"${skill.name}\" has no local executor. ` +\n `Implement execute() or switch to execution.type = \"mcp\" or \"a2a\".`\n )\n }\n }\n\n return {\n name: skill.name,\n description: skill.description,\n inputSchema: skill.inputSchema as unknown as Record<string, unknown>,\n outputSchema: skill.outputSchema as unknown as Record<string, unknown>,\n mode,\n execute: executeFn,\n /** If A2A, carry delegation metadata so the LLM can see it */\n a2aTargetAgentId: skill.execution?.type === 'a2a' ? (skill.execution as import('../core/types').A2ASkillExecution).targetAgentId : undefined,\n }\n }\n\n /** Call a tool on the publisher's MCP server (Closed skill). */\n private async _executeMCPTool(\n endpoint: string,\n toolName: string,\n params: Record<string, unknown>\n ): Promise<unknown> {\n const address = await this.wallet.getAddress()\n\n const timestamp = Math.floor(Date.now() / 1000)\n const message = `agentx:mcp:${toolName}:${timestamp}`\n const signature = await this.wallet.signMessage(message)\n\n const res = await fetch(endpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-Subscriber-Address': address,\n 'X-Signature': signature,\n 'X-Timestamp': String(timestamp),\n },\n body: JSON.stringify({\n method: 'tools/call',\n params: {\n name: toolName,\n arguments: params,\n },\n }),\n })\n\n if (!res.ok) {\n const text = await res.text()\n if (res.status === 403) {\n throw new AgentXError(\n AgentXErrorCode.SUBSCRIPTION_EXPIRED,\n `MCP server rejected request: subscription may have expired. ${text}`\n )\n }\n throw new AgentXError(\n AgentXErrorCode.TX_FAILED,\n `MCP tool \"${toolName}\" failed (HTTP ${res.status}): ${text}`\n )\n }\n\n const data = await res.json() as { content?: { type: string; text?: string }[] }\n const content = data.content?.[0]\n if (content?.type === 'text' && content.text) {\n try {\n return JSON.parse(content.text)\n } catch {\n return content.text\n }\n }\n return data\n }\n\n /**\n * Execute an A2A skill — delegate to another AgentX Agent.\n *\n * Standard Interface:\n * Input: { task, ...taskSpecificParams }\n * Output: { agentId, prompt, skills[] }\n *\n * The caller (LLM) receives the sub-Agent's prompt + skill list.\n * The LLM then decides how to use the sub-Agent — typically by\n * injecting the sub-Agent's system prompt and calling its skills.\n */\n private async _executeA2ASkill(\n skill: SkillDef,\n input: Record<string, unknown>\n ): Promise<A2ASkillResult> {\n const exec = skill.execution as import('../core/types').A2ASkillExecution\n if (!exec || exec.type !== 'a2a') {\n throw new AgentXError(\n AgentXErrorCode.INVALID_SCHEMA,\n `Skill \"${skill.name}\" is not an A2A delegation skill`\n )\n }\n\n const targetAgentId = exec.targetAgentId\n\n // Load the target Agent's full context\n let subContext: AgentRunContext\n try {\n subContext = await this.useAgent(targetAgentId)\n } catch (e) {\n throw new AgentXError(\n AgentXErrorCode.AGENT_NOT_FOUND,\n `A2A delegation failed: cannot load Agent #${targetAgentId}. ${e}`\n )\n }\n\n // Apply skill filter if specified\n if (exec.skillFilter && exec.skillFilter.length > 0) {\n const filterSet = new Set(exec.skillFilter)\n subContext = {\n ...subContext,\n skills: subContext.skills.filter(s => filterSet.has(s.name)),\n }\n }\n\n // Apply prompt override if specified\n if (exec.promptOverride) {\n subContext = { ...subContext, prompt: exec.promptOverride }\n }\n\n return {\n agentId: targetAgentId,\n prompt: subContext.prompt,\n skills: subContext.skills.map(s => ({\n name: s.name,\n description: s.description,\n inputSchema: s.inputSchema,\n })),\n // Pass the caller's input to the sub-agent's context\n callerInput: input,\n }\n }\n\n private async _getPrivateKey(): Promise<string> {\n if (this.wallet.getPrivateKey) return this.wallet.getPrivateKey()\n throw new AgentXError(\n AgentXErrorCode.WALLET_NOT_CONNECTED,\n 'Wallet must support getPrivateKey() for ECIES decryption.'\n )\n }\n}\n","// ---------------------------------------------------------------------------\n// @agentx/sdk — Configuration\n// ---------------------------------------------------------------------------\n// Wraps ConfigurationRegistry contract for key-value settings.\n// ---------------------------------------------------------------------------\n\nimport { stringToHex, hexToString } from 'viem'\nimport type { PublicClient, WalletClient, Address, Hash } from 'viem'\n\nconst CONFIG_ABI = {\n setConfig: {\n inputs: [{ name: 'key', type: 'string' }, { name: 'value', type: 'bytes' }] as const,\n name: 'setConfig' as const,\n outputs: [] as const,\n stateMutability: 'nonpayable' as const,\n type: 'function' as const,\n },\n getConfig: {\n inputs: [{ name: 'key', type: 'string' }] as const,\n name: 'getConfig' as const,\n outputs: [{ name: '', type: 'bytes' }] as const,\n stateMutability: 'view' as const,\n type: 'function' as const,\n },\n getAllConfig: {\n inputs: [] as const,\n name: 'getAllConfig' as const,\n outputs: [{ name: '', type: 'tuple[]', components: [{ name: 'key', type: 'string' }, { name: 'value', type: 'bytes' }] }] as const,\n stateMutability: 'view' as const,\n type: 'function' as const,\n },\n} as const\n\n// ── Known chain configs ────────────────────────────────────────────────────\n\n// Moves these to a separate file when the list grows.\n\nexport interface ChainConfig {\n chainId: number\n contracts: {\n identityRegistry: Address\n subscriptionManager: Address\n paymentGateway: Address\n a2aProtocolRegistry: Address\n reputationRegistry: Address\n configurationRegistry: Address\n }\n ipfsGateways: string[]\n rpcUrl?: string\n}\n\nexport const KNOWN_CHAINS: Record<number, ChainConfig> = {\n // Sepolia\n // Sepolia v2 (deployed 2026-07-13): platformFee=500bps(5%), multi-currency, trial escrow\n 11155111: {\n chainId: 11155111,\n contracts: {\n identityRegistry: '0xe94ad380d3F8d08a7590eda0C84f354a93F96e5F',\n subscriptionManager: '0xC15fE80b9d800abb72121F353a6ae6d6E9077E63',\n paymentGateway: '0x0000000000000000000000000000000000000000',\n a2aProtocolRegistry: '0x0000000000000000000000000000000000000000',\n reputationRegistry: '0x0000000000000000000000000000000000000000',\n configurationRegistry: '0x0000000000000000000000000000000000000000',\n },\n ipfsGateways: ['ipfs.io', 'gateway.pinata.cloud', 'dweb.link', 'cf-ipfs.com'],\n },\n}\n\n// ── Config Registry ────────────────────────────────────────────────────────\n\nexport interface ConfigRegistryOpts {\n contractAddress: Address\n publicClient: PublicClient\n walletClient: WalletClient\n}\n\nexport class ConfigurationRegistry {\n private address: Address\n private publicClient: PublicClient\n private walletClient: WalletClient\n\n constructor(opts: ConfigRegistryOpts) {\n this.address = opts.contractAddress\n this.publicClient = opts.publicClient\n this.walletClient = opts.walletClient\n }\n\n private get account(): Promise<Address> {\n return this.walletClient.getAddresses().then(a => {\n if (!a[0]) throw new Error('Wallet not connected')\n return a[0]\n })\n }\n\n async set(key: string, value: string): Promise<Hash> {\n const acct = await this.account\n const { request } = await this.publicClient.simulateContract({\n account: acct,\n address: this.address,\n abi: [CONFIG_ABI.setConfig],\n functionName: 'setConfig',\n args: [key, stringToHex(value)],\n })\n return this.walletClient.writeContract(request)\n }\n\n async get(key: string): Promise<string> {\n const r = await this.publicClient.readContract({\n address: this.address,\n abi: [CONFIG_ABI.getConfig],\n functionName: 'getConfig',\n args: [key],\n })\n return hexToString(r as `0x${string}`)\n }\n\n async getAll(): Promise<Record<string, string>> {\n const r = await this.publicClient.readContract({\n address: this.address,\n abi: [CONFIG_ABI.getAllConfig],\n functionName: 'getAllConfig',\n })\n const map: Record<string, string> = {}\n for (const { key, value } of r as { key: string; value: string }[]) {\n map[key] = hexToString(value as `0x${string}`)\n }\n return map\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/react/useAgentRunner.ts","../../src/core/crypto.ts","../../src/registry/ipfs-fetcher.ts","../../src/core/types.ts","../../src/agent/agent-runner.ts","../../src/config/config.ts"],"sourcesContent":["// ---------------------------------------------------------------------------\n// @agentx/sdk — useAgentRunner React Hook\n// ---------------------------------------------------------------------------\n// Wraps AgentRunner.useAgent() for React + wagmi integration.\n//\n// const { ctx, isLoading, error } = useAgentRunner(agentId)\n// // ctx.prompt → inject into LLM\n// // ctx.skills → RunnableSkill[] with execute()\n// // ctx.mcp → MCP connection info\n// ---------------------------------------------------------------------------\n\n'use client'\n\nimport { useState, useEffect, useRef } from 'react'\nimport { usePublicClient, useWalletClient } from 'wagmi'\nimport type { Address } from 'viem'\n\nimport { AgentRunner } from '../agent/agent-runner'\nimport type { AgentRunContext, OnChainReader } from '../agent/agent-runner'\nimport { IPFSFetcher } from '../registry/ipfs-fetcher'\nimport { KNOWN_CHAINS } from '../config/config'\nimport type { ChainConfig } from '../config/config'\n\n// ── IdentityRegistry ABI (minimal — only what useAgent needs) ──────────────\n\nconst IDENTITY_REGISTRY_ABI = [\n // getAgentMetadata returns MetadataEntry[] with key+value strings\n {\n name: 'getAgentMetadata',\n type: 'function',\n stateMutability: 'view',\n inputs: [{ name: 'agentId', type: 'uint256' }],\n outputs: [\n {\n name: '',\n type: 'tuple[]',\n components: [\n { name: 'key', type: 'string' },\n { name: 'value', type: 'bytes' },\n ],\n },\n ],\n },\n] as const\n\n// ── SubscriptionManager ABI (minimal) ─────────────────────────────────────\n\nconst SUBSCRIPTION_MANAGER_ABI = [\n {\n name: 'hasActiveSubscription',\n type: 'function',\n stateMutability: 'view',\n inputs: [\n { name: 'subscriber', type: 'address' },\n { name: 'agentId', type: 'uint256' },\n ],\n outputs: [{ name: '', type: 'bool' }],\n },\n] as const\n\n// ── Hook Config ────────────────────────────────────────────────────────────\n\nexport interface UseAgentRunnerConfig {\n agentId: number\n chainConfig?: ChainConfig\n ipfsGateways?: string[]\n}\n\nexport interface UseAgentRunnerResult {\n ctx: AgentRunContext | null\n isLoading: boolean\n error: Error | null\n /** Re-trigger the load (e.g. after connecting wallet or subscribing) */\n refetch: () => void\n}\n\n// ── OnChainReader Implementation (viem) ────────────────────────────────────\n\nclass ViemOnChainReader implements OnChainReader {\n constructor(\n private publicClient: ReturnType<typeof usePublicClient>,\n private chainConfig: ChainConfig\n ) {}\n\n async getTokenURI(_agentId: number): Promise<string> {\n // tokenURI is standard ERC-721 metadata — not needed for our flow\n // Metadata is fetched via getAgentMetadata\n return ''\n }\n\n async getAttributes(agentId: number): Promise<Record<string, string>> {\n if (!this.publicClient) throw new Error('Public client not available')\n\n const entries = (await this.publicClient.readContract({\n address: this.chainConfig.contracts.identityRegistry,\n abi: IDENTITY_REGISTRY_ABI,\n functionName: 'getAgentMetadata',\n args: [BigInt(agentId)],\n })) as { key: string; value: string }[]\n\n const attrs: Record<string, string> = {}\n for (const entry of entries) {\n // value is bytes — convert to string\n const hexStr = entry.value\n if (hexStr && hexStr !== '0x') {\n attrs[entry.key] = hexToStringUTF8(hexStr)\n } else {\n attrs[entry.key] = ''\n }\n }\n return attrs\n }\n\n async hasActiveSubscription(address: string, agentId: number): Promise<boolean> {\n if (!this.publicClient) return false\n\n try {\n return (await this.publicClient.readContract({\n address: this.chainConfig.contracts.subscriptionManager,\n abi: SUBSCRIPTION_MANAGER_ABI,\n functionName: 'hasActiveSubscription',\n args: [address as Address, BigInt(agentId)],\n })) as boolean\n } catch {\n return false\n }\n }\n}\n\n// ── Helpers ────────────────────────────────────────────────────────────────\n\nfunction hexToStringUTF8(hex: string): string {\n if (!hex.startsWith('0x')) return hex\n const hexClean = hex.slice(2)\n if (hexClean.length === 0) return ''\n try {\n const bytes = new Uint8Array(hexClean.length / 2)\n for (let i = 0; i < bytes.length; i++) {\n bytes[i] = parseInt(hexClean.substring(i * 2, i * 2 + 2), 16)\n }\n return new TextDecoder().decode(bytes)\n } catch {\n return hex\n }\n}\n\n// ── Hook ───────────────────────────────────────────────────────────────────\n\nexport function useAgentRunner(config: UseAgentRunnerConfig): UseAgentRunnerResult {\n const { agentId, chainConfig: chainConfigOverride, ipfsGateways } = config\n\n const publicClient = usePublicClient()\n const { data: walletClient } = useWalletClient()\n\n const [ctx, setCtx] = useState<AgentRunContext | null>(null)\n const [isLoading, setIsLoading] = useState(false)\n const [error, setError] = useState<Error | null>(null)\n const [refetchKey, setRefetchKey] = useState(0)\n\n const runnerRef = useRef<AgentRunner | null>(null)\n const mountedRef = useRef(true)\n\n useEffect(() => {\n mountedRef.current = true\n return () => {\n mountedRef.current = false\n }\n }, [])\n\n useEffect(() => {\n if (!publicClient || !walletClient) {\n setError(new Error('Wallet not connected'))\n return\n }\n\n const chainConfig =\n chainConfigOverride ?? (publicClient.chain?.id ? KNOWN_CHAINS[publicClient.chain.id] : undefined)\n\n if (!chainConfig) {\n setError(new Error(`Chain ${publicClient.chain?.id} not supported`))\n return\n }\n\n // Create OnChainReader\n const reader = new ViemOnChainReader(publicClient, chainConfig)\n\n // WalletSigner from wagmi\n const signer = {\n async signMessage(message: string): Promise<string> {\n if (!walletClient.account) throw new Error('Wallet not connected')\n return walletClient.signMessage({ account: walletClient.account, message })\n },\n async getAddress(): Promise<string> {\n if (!walletClient.account) throw new Error('Wallet not connected')\n return walletClient.account.address\n },\n async getPrivateKey(): Promise<string> {\n // wagmi walletClient doesn't expose private key\n // ECIES decryption requires private key — must be injected from wallet provider\n throw new Error(\n 'Private key not available via wagmi. ' +\n 'Use window.ethereum.request({ method: \"eth_private_key\" }) or inject getPrivateKey via custom WalletSigner.'\n )\n },\n }\n\n // IPFS Fetcher\n const ipfsFetcher = new IPFSFetcher({\n fallbackGateways: ipfsGateways ?? chainConfig.ipfsGateways ?? [\n 'gateway.pinata.cloud',\n 'dweb.link',\n 'cf-ipfs.com',\n ],\n })\n\n runnerRef.current = new AgentRunner({\n reader,\n wallet: signer,\n ipfsFetcher,\n })\n\n setIsLoading(true)\n setError(null)\n\n runnerRef.current\n .useAgent(agentId)\n .then(result => {\n if (mountedRef.current) {\n setCtx(result)\n setIsLoading(false)\n }\n })\n .catch(err => {\n if (mountedRef.current) {\n setError(err instanceof Error ? err : new Error(String(err)))\n setIsLoading(false)\n }\n })\n\n return () => {\n mountedRef.current = false\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [agentId, publicClient?.chain?.id, publicClient, walletClient, refetchKey])\n\n const refetch = () => setRefetchKey(k => k + 1)\n\n return { ctx, isLoading, error, refetch }\n}\n","// ---------------------------------------------------------------------------\n// @agentx/sdk — Crypto Engine\n// ---------------------------------------------------------------------------\n// AES-256-GCM for content encryption (NIST standard, same wire format as\n// aihunter-saas for interop). ECIES (secp256k1) for key wrapping.\n//\n// Wire format (AES-256-GCM):\n// base64( IV[12] || ciphertext || authTag[16] )\n//\n// ECIES wire format (compatible with eciesjs):\n// hex( ephemeralPub[33] || IV[16] || ciphertext || MAC[32] )\n//\n// Pure JS — works in browser, Node, edge. No native deps except @noble/*.\n// ---------------------------------------------------------------------------\n\nimport { gcm } from '@noble/ciphers/aes.js'\nimport { secp256k1 } from '@noble/curves/secp256k1.js'\nimport { sha256 } from '@noble/hashes/sha2.js'\nimport { hkdf } from '@noble/hashes/hkdf.js'\nimport { hmac } from '@noble/hashes/hmac.js'\nimport { bytesToHex, hexToBytes } from '@noble/ciphers/utils.js'\n\n// ── randomBytes implementation (cross-runtime: browser / Node) ────────────\n\nexport function randomBytes(length: number): Uint8Array {\n // browser: crypto.getRandomValues\n if (typeof crypto !== 'undefined' && crypto.getRandomValues) {\n const buf = new Uint8Array(length)\n crypto.getRandomValues(buf)\n return buf\n }\n // Node: crypto.randomBytes\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const nodeCrypto = require('crypto')\n return new Uint8Array(nodeCrypto.randomBytes(length))\n}\n\nimport type { EncryptedPayload, AgentPrivatePayload } from './types'\nimport type { PackResult } from './types'\n\n// ── Re-exports for convenience ─────────────────────────────────────────────\n\nexport { bytesToHex, hexToBytes }\n\n// ── Constants ──────────────────────────────────────────────────────────────\n\nconst AES_KEY_SIZE = 32\nconst IV_SIZE = 12 // GCM recommended\nconst TAG_SIZE = 16 // GCM auth tag\n\n// ── Base64 helpers (cross-runtime) ─────────────────────────────────────────\n\nfunction toBase64(bytes: Uint8Array): string {\n // Works in browser (btoa + binary) and Node (Buffer)\n if (typeof Buffer !== 'undefined') return Buffer.from(bytes).toString('base64')\n let binary = ''\n for (let i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i]!)\n return btoa(binary)\n}\n\nfunction fromBase64(b64: string): Uint8Array {\n if (typeof Buffer !== 'undefined') return new Uint8Array(Buffer.from(b64, 'base64'))\n const binary = atob(b64)\n const bytes = new Uint8Array(binary.length)\n for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i)\n return bytes\n}\n\n// ── AES-256-GCM ────────────────────────────────────────────────────────────\n\n/**\n * Encrypt with AES-256-GCM.\n * Wire format (same as aihunter-saas): base64( IV[12] || ciphertext || authTag[16] )\n */\nexport function aesEncrypt(plaintext: string, keyHex: string): string {\n const key = hexToBytes(keyHex)\n const iv = randomBytes(IV_SIZE)\n const plainBytes = new TextEncoder().encode(plaintext)\n\n const cipher = gcm(key, iv)\n const encrypted = cipher.encrypt(plainBytes)\n // noble gcm.encrypt returns: ciphertext || authTag(16)\n const ciphertext = encrypted.subarray(0, -TAG_SIZE)\n const authTag = encrypted.subarray(-TAG_SIZE)\n\n // Pack: IV || ciphertext || authTag\n const combined = new Uint8Array(IV_SIZE + ciphertext.length + TAG_SIZE)\n combined.set(iv, 0)\n combined.set(ciphertext, IV_SIZE)\n combined.set(authTag, IV_SIZE + ciphertext.length)\n\n return toBase64(combined)\n}\n\n/**\n * Decrypt AES-256-GCM (same wire format as aihunter-saas).\n */\nexport function aesDecrypt(encryptedBase64: string, keyHex: string): string {\n const key = hexToBytes(keyHex)\n const combined = fromBase64(encryptedBase64)\n\n const iv = combined.subarray(0, IV_SIZE)\n const ciphertext = combined.subarray(IV_SIZE, -TAG_SIZE)\n const authTag = combined.subarray(-TAG_SIZE)\n\n const cipher = gcm(key, iv)\n // noble decrypt expects: ciphertext || authTag\n const ciphertextWithTag = new Uint8Array(ciphertext.length + TAG_SIZE)\n ciphertextWithTag.set(ciphertext, 0)\n ciphertextWithTag.set(authTag, ciphertext.length)\n\n const decrypted = cipher.decrypt(ciphertextWithTag)\n return new TextDecoder().decode(decrypted)\n}\n\n/**\n * Generate a cryptographically random AES-256 key (hex, 64 chars).\n */\nexport function generateAesKey(): string {\n return bytesToHex(randomBytes(AES_KEY_SIZE))\n}\n\n// ── ECIES (secp256k1) ──────────────────────────────────────────────────────\n//\n// eciesjs-compatible wire format:\n// ephemeralPub(33B compressed) || IV(16B) || ciphertext || MAC(32B)\n// Encoding: hex\n//\n// HKDF(SHA-256) derives AES key + HMAC key from ECDH shared secret.\n// ---------------------------------------------------------------------------\n\nfunction eciesEncode(\n ephemeralPub: Uint8Array,\n iv: Uint8Array,\n ciphertext: Uint8Array,\n mac: Uint8Array\n): string {\n const out = new Uint8Array(33 + 16 + ciphertext.length + 32)\n out.set(ephemeralPub, 0)\n out.set(iv, 33)\n out.set(ciphertext, 33 + 16)\n out.set(mac, 33 + 16 + ciphertext.length)\n return bytesToHex(out)\n}\n\nfunction eciesDecode(dataHex: string): {\n ephemeralPub: Uint8Array\n iv: Uint8Array\n ciphertext: Uint8Array\n mac: Uint8Array\n} {\n const d = hexToBytes(dataHex)\n return {\n ephemeralPub: d.subarray(0, 33),\n iv: d.subarray(33, 49),\n ciphertext: d.subarray(49, -32),\n mac: d.subarray(-32),\n }\n}\n\n// Simple AES-256-CTR implementation on top of @noble/ciphers AES core\nfunction aesCtrEncrypt(key: Uint8Array, ctrBytes: Uint8Array, data: Uint8Array): Uint8Array {\n const blockSize = 16\n const cipher = gcm(key, ctrBytes) // GCM internally handles CTR\n // Use noble's CTR approach: encrypt the plaintext directly with the derived stream\n // noble uses AES-CTR internally for GCM; simpler: implement CTR with AES-ECB\n const result = new Uint8Array(data.length)\n const counter = new Uint8Array(blockSize)\n counter.set(ctrBytes)\n for (let i = 0; i < data.length; i += blockSize) {\n const keystream = gcm(key, counter).encrypt(new Uint8Array(blockSize))\n for (let j = 0; j < blockSize && i + j < data.length; j++) {\n result[i + j] = keystream[j]! ^ data[i + j]!\n }\n // Increment counter (big-endian)\n for (let j = blockSize - 1; j >= 0; j--) {\n const val = counter[j]\n if (val !== undefined) {\n counter[j] = (val + 1) & 0xff\n if (counter[j] !== 0) break\n }\n }\n }\n return result\n}\n\n/**\n * Encrypt data with recipient's secp256k1 public key (ECIES).\n *\n * @param dataHex The data to encrypt (hex, e.g. AES key)\n * @param publicKey Recipient's public key (hex, 04-prefixed uncompressed or 02/03 compressed)\n */\nexport function eciesEncrypt(dataHex: string, publicKey: string): string {\n // 1. Ephemeral keypair\n const ephPriv = randomBytes(32)\n const ephPub = secp256k1.getPublicKey(ephPriv, true) // 33B compressed\n\n // 2. Parse recipient public key\n let recipientPub: Uint8Array\n if (publicKey.startsWith('04') && publicKey.length === 130) {\n recipientPub = hexToBytes(publicKey)\n } else if (publicKey.startsWith('02') || publicKey.startsWith('03')) {\n recipientPub = hexToBytes(publicKey)\n } else {\n throw new Error('Invalid public key format: expected hex with 02/03/04 prefix')\n }\n\n // 3. ECDH\n const shared = secp256k1.getSharedSecret(ephPriv, recipientPub)\n const sharedX = shared.subarray(1, 33) // x-coordinate only\n const sharedKey = sha256(sharedX)\n\n // 4. HKDF: encKey(32) || macKey(32)\n const hkdfOut = hkdf(sha256, sharedKey, undefined, undefined, 64)\n const encKey = hkdfOut.subarray(0, 32)\n const macKey = hkdfOut.subarray(32, 64)\n\n // 5. AES-256-CTR encrypt\n const iv = randomBytes(16)\n const plaintext = hexToBytes(dataHex)\n const ciphertext = aesCtrEncrypt(encKey, iv, plaintext)\n\n // 6. HMAC: MAC(ephemeralPub || IV || ciphertext)\n const macInput = new Uint8Array(33 + 16 + ciphertext.length)\n macInput.set(ephPub, 0)\n macInput.set(iv, 33)\n macInput.set(ciphertext, 33 + 16)\n const mac = hmac(sha256, macKey, macInput)\n\n return eciesEncode(ephPub, iv, ciphertext, mac)\n}\n\n/**\n * Decrypt ECIES ciphertext with recipient's secp256k1 private key.\n */\nexport function eciesDecrypt(dataHex: string, privateKey: string): string {\n const { ephemeralPub, iv, ciphertext, mac } = eciesDecode(dataHex)\n\n // 1. ECDH\n const privBytes = hexToBytes(privateKey)\n const shared = secp256k1.getSharedSecret(privBytes, ephemeralPub)\n const sharedX = shared.subarray(1, 33)\n const sharedKey = sha256(sharedX)\n\n // 2. HKDF\n const hkdfOut = hkdf(sha256, sharedKey, undefined, undefined, 64)\n const encKey = hkdfOut.subarray(0, 32)\n const macKey = hkdfOut.subarray(32, 64)\n\n // 3. Verify MAC\n const macInput = new Uint8Array(33 + 16 + ciphertext.length)\n macInput.set(ephemeralPub, 0)\n macInput.set(iv, 33)\n macInput.set(ciphertext, 33 + 16)\n const expectedMac = hmac(sha256, macKey, macInput)\n if (!constantTimeEqual(mac, expectedMac)) {\n throw new Error('ECIES decryption failed: MAC mismatch')\n }\n\n // 4. Decrypt\n const plaintext = aesCtrEncrypt(encKey, iv, ciphertext) // CTR encrypt = decrypt\n return bytesToHex(plaintext)\n}\n\nfunction constantTimeEqual(a: Uint8Array, b: Uint8Array): boolean {\n if (a.length !== b.length) return false\n let diff = 0\n for (let i = 0; i < a.length; i++) diff |= a[i]! ^ b[i]!\n return diff === 0\n}\n\n// ── High-Level: Agent Pack / Unpack ────────────────────────────────────────\n\n/**\n * Encrypt an Agent's private payload with AES-256-GCM.\n */\nexport function encryptPayload(\n payload: AgentPrivatePayload,\n keyHex?: string\n): EncryptedPayload {\n const key = keyHex ?? generateAesKey()\n return {\n encrypted: true,\n algorithm: 'AES-256-GCM',\n data: aesEncrypt(JSON.stringify(payload), key),\n }\n}\n\n/**\n * Decrypt an EncryptedPayload.\n */\nexport function decryptPayload(\n encrypted: EncryptedPayload,\n keyHex: string\n): AgentPrivatePayload {\n if (encrypted.algorithm !== 'AES-256-GCM') {\n throw new Error(`Unsupported algorithm: ${encrypted.algorithm}`)\n }\n return JSON.parse(aesDecrypt(encrypted.data, keyHex)) as AgentPrivatePayload\n}\n\n/**\n * Pack an AgentPayload for publishing.\n * 1. Split public/private\n * 2. AES-256-GCM encrypt private part\n * 3. ECIES wrap AES key with creator's public key\n */\nexport function packAgentForPublish(\n agent: import('./types').AgentPayload,\n publicKey: string,\n aesKeyHex?: string\n): PackResult {\n const key = aesKeyHex ?? generateAesKey()\n\n const eciesEncryptedKeyHex = eciesEncrypt(key, publicKey)\n\n return {\n encryptedCid: '', // filled after IPFS upload\n publicCid: '', // filled after IPFS upload\n aesKeyHex: key,\n eciesEncryptedKeyHex,\n }\n}\n\n/**\n * Unpack an Agent:\n * 1. ECIES decrypt the AES key (private key)\n * 2. AES-256-GCM decrypt the payload\n */\nexport function unpackAgent(\n encryptedPayload: EncryptedPayload,\n eciesEncryptedKey: string,\n privateKey: string\n): AgentPrivatePayload {\n const aesKeyHex = eciesDecrypt(eciesEncryptedKey, privateKey)\n return decryptPayload(encryptedPayload, aesKeyHex)\n}\n\n// ── Key Pair Utilities ─────────────────────────────────────────────────────\n\n/**\n * Generate a secp256k1 keypair compatible with Ethereum wallets.\n */\nexport function generateKeyPair(): { privateKey: string; publicKey: string } {\n const priv = randomBytes(32)\n const pub = secp256k1.getPublicKey(priv, false) // uncompressed 04-prefixed\n return { privateKey: bytesToHex(priv), publicKey: bytesToHex(pub) }\n}\n\n/**\n * Derive public key from private key (hex).\n */\nexport function getPublicKey(privateKey: string): string {\n return bytesToHex(secp256k1.getPublicKey(hexToBytes(privateKey), false))\n}\n","// ---------------------------------------------------------------------------\n// @agentx/sdk — IPFS Fetcher\n// ---------------------------------------------------------------------------\n// Multi-gateway IPFS fetcher with in-memory cache, deduplication, and\n// automatic fallback. Compatible with the EncryptedPayload wire format.\n// ---------------------------------------------------------------------------\n\nimport type { EncryptedPayload } from '../core/types'\n\n// ── Types ───────────────────────────────────────────────────────────────────\n\nexport interface IPFSFetcherConfig {\n /** Primary IPFS gateway (default: ipfs.io) */\n gateway?: string\n /** Fallback gateways in order of preference */\n fallbackGateways?: string[]\n /** Request timeout in ms (default: 10_000) */\n timeoutMs?: number\n /** Max cached entries (LRU-like eviction, default: 200) */\n maxCache?: number\n}\n\ntype CacheEntry<T> = {\n data: T\n timestamp: number\n}\n\n// ── Implementation ─────────────────────────────────────────────────────────\n\nexport class IPFSFetcher {\n private gateway: string\n private fallbackGateways: string[]\n private timeoutMs: number\n\n private cache = new Map<string, CacheEntry<unknown>>()\n private maxCache: number\n private pending = new Map<string, Promise<unknown>>()\n private failed = new Set<string>()\n\n constructor(config: IPFSFetcherConfig = {}) {\n this.gateway = config.gateway ?? 'ipfs.io'\n this.fallbackGateways = config.fallbackGateways ?? [\n 'gateway.pinata.cloud',\n 'dweb.link',\n 'cf-ipfs.com',\n ]\n this.timeoutMs = config.timeoutMs ?? 10_000\n this.maxCache = config.maxCache ?? 200\n }\n\n // ── Public API ──────────────────────────────────────────────────────────\n\n /** Fetch JSON from a single IPFS CID. */\n async fetchJSON<T = unknown>(cid: string): Promise<T> {\n const cached = this.cache.get(cid)\n if (cached) return cached.data as T\n\n if (this.failed.has(cid)) throw new Error(`CID ${cid} previously failed`)\n\n const pending = this.pending.get(cid)\n if (pending) return pending as Promise<T>\n\n const promise = this._doFetch<T>(cid)\n this.pending.set(cid, promise)\n\n try {\n const data = await promise\n this._cacheSet(cid, data)\n return data\n } catch (e) {\n this.failed.add(cid)\n throw e\n } finally {\n this.pending.delete(cid)\n }\n }\n\n /** Fetch encrypted agent payload (validates algorithm). */\n async fetchEncryptedPayload(cid: string): Promise<EncryptedPayload> {\n const raw = await this.fetchJSON<Record<string, unknown>>(cid)\n if (!raw.encrypted || raw.algorithm !== 'AES-256-GCM' || typeof raw.data !== 'string') {\n throw new Error(`Invalid EncryptedPayload at CID ${cid}`)\n }\n return raw as unknown as EncryptedPayload\n }\n\n /** Batch fetch multiple CIDs with concurrency control. */\n async fetchBatch<T = unknown>(cids: string[], concurrency = 5): Promise<Map<string, T>> {\n const results = new Map<string, T>()\n const unique = [...new Set(cids)].filter(c => this.isValidCID(c))\n\n for (let i = 0; i < unique.length; i += concurrency) {\n const batch = unique.slice(i, i + concurrency)\n const settled = await Promise.allSettled(\n batch.map(cid => this.fetchJSON<T>(cid))\n )\n settled.forEach((r, j) => {\n if (r.status === 'fulfilled') results.set(batch[j]!, r.value)\n })\n if (i + concurrency < unique.length) {\n await new Promise(r => setTimeout(r, 200))\n }\n }\n return results\n }\n\n /** Check if a string looks like a valid IPFS CID. */\n isValidCID(cid: string): boolean {\n return /^(Qm[1-9A-HJ-NP-Za-km-z]{44,}|b[a-z2-7]{58,}|[A-Za-z0-9+/]{46,})$/.test(cid)\n }\n\n /** Clear cache (optionally for a specific CID). */\n clearCache(cid?: string): void {\n if (cid) {\n this.cache.delete(cid)\n } else {\n this.cache.clear()\n }\n this.failed.clear()\n }\n\n /** Number of cached entries. */\n get cacheSize(): number {\n return this.cache.size\n }\n\n // ── Internal ─────────────────────────────────────────────────────────────\n\n private async _doFetch<T>(cid: string): Promise<T> {\n if (!this.isValidCID(cid)) throw new Error(`Invalid CID: ${cid}`)\n\n // Try primary gateway\n try {\n return await this._fetchFrom(cid, this.gateway, this.timeoutMs)\n } catch {\n // fall through to alternatives\n }\n\n // Try fallback gateways\n for (const gw of this.fallbackGateways) {\n try {\n return await this._fetchFrom(cid, gw, this.timeoutMs)\n } catch {\n // try next\n }\n }\n\n throw new Error(`All IPFS gateways failed for CID ${cid}`)\n }\n\n private async _fetchFrom<T>(cid: string, gateway: string, timeoutMs: number): Promise<T> {\n const url = `https://${gateway}/ipfs/${cid}`\n const res = await fetch(url, {\n headers: { Accept: 'application/json' },\n signal: AbortSignal.timeout(timeoutMs),\n })\n if (!res.ok) throw new Error(`HTTP ${res.status}`)\n return (await res.json()) as T\n }\n\n private _cacheSet(cid: string, data: unknown): void {\n this.cache.set(cid, { data, timestamp: Date.now() })\n // Simple LRU-like eviction\n if (this.cache.size > this.maxCache) {\n const oldest = [...this.cache.entries()].sort(\n (a, b) => a[1].timestamp - b[1].timestamp\n )[0]\n if (oldest) this.cache.delete(oldest[0])\n }\n }\n}\n\n/** Singleton-friendly default instance. */\nexport const defaultIPFSFetcher = new IPFSFetcher()\n","// ---------------------------------------------------------------------------\n// @agentx/sdk — Core Type Definitions\n// ---------------------------------------------------------------------------\n// Agent = Prompt + Skills[] + MCP\n// All crypto-related \"wire\" fields (encryptedPayloadCid, eciesEncryptedKey)\n// live in IPFS metadata attributes → existing ERC8004 contracts are unchanged.\n// ---------------------------------------------------------------------------\n\n// ── JSON Schema (MCP standard subset) ──────────────────────────────────────\n\nexport interface JSONSchema {\n type: 'object' | 'array' | 'string' | 'number' | 'boolean' | 'integer' | 'null'\n properties?: Record<string, JSONSchemaProperty>\n required?: string[]\n description?: string\n items?: JSONSchema\n enum?: (string | number | boolean | null)[]\n}\n\nexport interface JSONSchemaProperty {\n type?: JSONSchema['type'] | JSONSchema['type'][]\n description?: string\n properties?: Record<string, JSONSchemaProperty>\n required?: string[]\n items?: JSONSchema\n enum?: (string | number | boolean | null)[]\n format?: string\n default?: unknown\n}\n\n// ── Skill Definition ───────────────────────────────────────────────────────\n\n/**\n * A single skill module that an Agent exposes.\n * `inputSchema` and `outputSchema` follow MCP Tool JSON Schema conventions.\n */\nexport interface SkillDef {\n /** Unique skill name (e.g. \"solidity_audit\") */\n name: string\n /** Human-readable description shown in the marketplace */\n description: string\n /** Semantic version of this skill */\n version: string\n /** JSON Schema for the tool's input parameters */\n inputSchema: JSONSchema\n /** JSON Schema for the tool's output return value */\n outputSchema?: JSONSchema\n /**\n * Execution mode.\n * - undefined / \"open\": Source is in the encrypted payload, runs locally.\n * - { type: \"mcp\", toolName: \"...\" }: Source lives on the publisher's\n * MCP server. Subscriber only gets Schema + remote execution endpoint.\n * MCP server verifies on-chain subscription on every call.\n * - { type: \"a2a\", targetAgentId: 42 }: Delegates to another AgentX Agent.\n * The caller's AgentRunner loads + decrypts the target Agent, injects\n * its prompt into the LLM context, and exposes its skills as callable\n * tools. This is the core Agent Composition primitive.\n */\n execution?: SkillExecutionRemote | A2ASkillExecution\n}\n\n/** Where the skill code actually runs. */\nexport type SkillExecutionMode = 'open' | 'mcp' | 'a2a'\n\nexport interface SkillExecutionRemote {\n type: 'mcp'\n /** MCP tool name on the publisher's server (e.g. \"run_strategy_abc123\") */\n toolName: string\n /** Optional: explicit MCP endpoint override */\n endpoint?: string\n}\n\n/**\n * A2A Skill Execution — delegate to another AgentX Agent.\n *\n * Example: A \"trading\" Agent has a skill:\n * execution: { type: \"a2a\", targetAgentId: 42 }\n * → When LLM calls this skill, AgentRunner loads Agent #42,\n * decrypts its prompt+skills, and the sub-Agent runs in the\n * same LLM conversation with its own system prompt.\n */\nexport interface A2ASkillExecution {\n type: 'a2a'\n /** On-chain Agent ID to delegate to */\n targetAgentId: number\n /** Optional: restrict which of the target Agent's skills are exposed */\n skillFilter?: string[]\n /** Optional: custom system prompt override for the sub-Agent */\n promptOverride?: string\n}\n\n// ── MCP Connection ─────────────────────────────────────────────────────────\n\nexport type McpTransport = 'http' | 'sse' | 'stdio'\n\nexport interface McpConnection {\n /** Transport type */\n type: McpTransport\n /** MCP server URL (required for http/sse) */\n url?: string\n /** Optional: limit which tools the Agent exposes to users */\n toolFilter?: string[]\n /** Optional: MCP server authentication header / key */\n authHeader?: string\n}\n\n// ── Pricing ────────────────────────────────────────────────────────────────\n\nexport type PricingType = 'subscription' | 'pay_per_use' | 'free'\n\nexport interface AgentPricing {\n type: PricingType\n /** Amount in native unit (e.g. \"0.01\" for 0.01 ETH) */\n amount: string\n /** ERC20 token address, or empty for native currency */\n currency: string\n /** Billing period for subscriptions (e.g. \"month\", \"year\", \"day\") */\n period?: string\n}\n\n// ── Agent Payload (the core data model) ────────────────────────────────────\n\n/**\n * The complete Agent definition.\n *\n * - Fields above \"--- private payload ---\" are public (IPFS publicPayloadCid).\n * - Fields below are encrypted with AES-256-GCM and stored at encryptedPayloadCid.\n */\nexport interface AgentPayload {\n // ── Public (visible in marketplace, stored at publicPayloadCid) ─────────\n name: string\n description: string\n image?: string\n version: string\n tags: string[]\n capabilities: string[]\n supportedTasks: string[]\n communicationProtocol: 'mcp' | 'a2a'\n authenticationMethod: 'ecdsa'\n pricing: AgentPricing\n\n // ── Private (AES-256-GCM encrypted, stored at encryptedPayloadCid) ──────\n prompt: string\n skills: SkillDef[]\n mcp: McpConnection\n}\n\n/** Subset of AgentPayload that is publicly visible */\nexport type AgentPublicPayload = Omit<\n AgentPayload,\n 'prompt' | 'skills' | 'mcp'\n>\n\n/** Fields that must be encrypted before IPFS upload */\nexport type AgentPrivatePayload = Pick<\n AgentPayload,\n 'prompt' | 'skills' | 'mcp'\n>\n\n// ── Encrypted Payload (IPFS wire format) ───────────────────────────────────\n\nexport interface EncryptedPayload {\n encrypted: true\n algorithm: 'AES-256-GCM'\n /** base64(iv + ciphertext + authTag) */\n data: string\n}\n\n// ── On-Chain Metadata (stored in ERC-721 tokenURI attributes) ─────────────\n\nexport interface OnChainAgentMetadata {\n tokenURI: string\n attributes: {\n name: string\n description: string\n /** CID of the AES-256-GCM encrypted payload on IPFS */\n encryptedPayloadCid: string\n /** ECIES-encrypted AES key (secp256k1, hex string) */\n eciesEncryptedKey: string\n /** CID of the public metadata on IPFS */\n publicPayloadCid: string\n capabilities: string[]\n skills: string[]\n mcpEndpoint: string\n version: string\n tags: string[]\n pricingType: PricingType\n pricingAmount: string\n }\n}\n\n// ── Agent Registry ─────────────────────────────────────────────────────────\n\nexport interface RegisteredAgent {\n /** ERC-721 token ID (= agentId) */\n agentId: number\n /** Owner wallet address */\n owner: string\n /** Creator wallet address */\n creator: string\n /** Full on-chain metadata */\n metadata: OnChainAgentMetadata\n /** Block number where agent was registered */\n registeredAt: number\n /** IPFS CID of the full public payload (resolved from tokenURI) */\n publicPayloadCid: string\n}\n\n// ── Agent Search ───────────────────────────────────────────────────────────\n\nexport interface AgentSearchQuery {\n keyword?: string\n capabilities?: string[]\n tags?: string[]\n pricingType?: PricingType\n maxPrice?: string\n owner?: string\n sortBy?: 'latest' | 'reputation' | 'price_asc' | 'price_desc'\n page?: number\n pageSize?: number\n}\n\nexport interface AgentSearchResult {\n agents: RegisteredAgent[]\n total: number\n page: number\n pageSize: number\n}\n\n// ── Subscription ───────────────────────────────────────────────────────────\n\nexport type SubscriptionStatus = 'active' | 'expired' | 'cancelled' | 'pending'\n\nexport interface AgentSubscription {\n subscriptionId: number\n subscriber: string\n agentId: number\n status: SubscriptionStatus\n startedAt: number\n expiresAt: number\n period: string\n}\n\n// ── A2A Protocol ───────────────────────────────────────────────────────────\n\nexport type A2ATaskStatus = 'created' | 'accepted' | 'in_progress' | 'completed' | 'failed'\n\nexport interface A2AAgentCard {\n agentId: number\n name: string\n capabilities: string[]\n supportedTasks: string[]\n /** MCP endpoint URL for direct agent-to-agent communication */\n endpoint: string\n /** Public key for ECDSA authentication */\n publicKey: string\n}\n\nexport interface A2ATask {\n taskId: number\n /** Agent that created the task */\n creator: string\n /** Target agent to execute the task */\n targetAgentId: number\n /** Task type (must be in target's supportedTasks) */\n taskType: string\n /** JSON input payload */\n input: string\n status: A2ATaskStatus\n result?: string\n createdAt: number\n completedAt?: number\n}\n\n// ── Reputation ─────────────────────────────────────────────────────────────\n\nexport interface AgentReputation {\n agentId: number\n averageRating: number\n totalRatings: number\n reviews: AgentReview[]\n}\n\nexport interface AgentReview {\n reviewer: string\n rating: number // 1-5\n comment: string\n timestamp: number\n}\n\n// ── AgentX Client Configuration ────────────────────────────────────────────\n\nexport interface AgentXConfig {\n /** Chain ID (e.g. 11155111 for Sepolia) */\n chainId: number\n /** RPC endpoint override (uses viem's default if omitted) */\n rpcUrl?: string\n /** Contract addresses for the current chain */\n contracts: AgentXContracts\n /** IPFS gateway URLs (ordered by priority) */\n ipfsGateways: string[]\n /** Default IPFS pinning service */\n pinningService?: 'pinata'\n pinataJwt?: string\n}\n\nexport interface AgentXContracts {\n identityRegistry: `0x${string}`\n subscriptionManager: `0x${string}`\n paymentGateway: `0x${string}`\n a2aProtocolRegistry: `0x${string}`\n reputationRegistry: `0x${string}`\n configurationRegistry: `0x${string}`\n}\n\n// ── Agent Packing / Unpacking Result ───────────────────────────────────────\n\nexport interface PackResult {\n /** CID of AES-256-GCM encrypted payload on IPFS */\n encryptedCid: string\n /** CID of public metadata on IPFS */\n publicCid: string\n /** Raw AES key (hex) — DO NOT share or upload this */\n aesKeyHex: string\n /** ECIES-encrypted AES key (hex), safe to store on-chain */\n eciesEncryptedKeyHex: string\n}\n\nexport interface UnpackResult {\n /** Decrypted AgentPayload */\n agent: AgentPayload\n /** CID where the encrypted payload was fetched from */\n encryptedCid: string\n /** CID of the public metadata */\n publicCid: string\n}\n\n// ── Error Types ────────────────────────────────────────────────────────────\n\nexport enum AgentXErrorCode {\n NOT_SUBSCRIBED = 'NOT_SUBSCRIBED',\n SUBSCRIPTION_EXPIRED = 'SUBSCRIPTION_EXPIRED',\n DECRYPTION_FAILED = 'DECRYPTION_FAILED',\n IPFS_FETCH_FAILED = 'IPFS_FETCH_FAILED',\n AGENT_NOT_FOUND = 'AGENT_NOT_FOUND',\n INVALID_SCHEMA = 'INVALID_SCHEMA',\n TX_FAILED = 'TX_FAILED',\n WALLET_NOT_CONNECTED = 'WALLET_NOT_CONNECTED',\n}\n\nexport class AgentXError extends Error {\n code: AgentXErrorCode\n /** If NOT_SUBSCRIBED, carry enough info for wallet/X402 auto-payment */\n paymentInfo?: SubscriptionRequired\n constructor(code: AgentXErrorCode, message: string) {\n super(message)\n this.code = code\n this.name = 'AgentXError'\n }\n}\n\n/**\n * Structured info for wallet/X402 auto-subscription.\n * Thrown by AgentRunner.useAgent() when the user/Agent has no\n * active subscription.\n */\nexport interface SubscriptionRequired {\n agentId: number\n /** Plan IDs available for this Agent (on-chain query) */\n plans?: { planId: number; price: bigint; period: string; payToken: string; trialDays: number }[]\n}\n","// ---------------------------------------------------------------------------\n// @agentx/sdk — Agent Runner\n// ---------------------------------------------------------------------------\n// The unified entry point for \"using\" an Agent.\n//\n// const runner = new AgentRunner({ reader, wallet })\n// const ctx = await runner.useAgent(42)\n// // ctx.prompt → system prompt for LLM\n// // ctx.skills → [{ name, description, inputSchema, execute }]\n// // ctx.mcp → MCP connection info\n//\n// 对于 Open Skill: 直接本地执行(源码在解密后的 payload 里)\n// 对于 Closed Skill:通过 MCP 远程调用 → 发布者服务器执行 + 校验订阅\n// ---------------------------------------------------------------------------\n\nimport { eciesEncrypt, generateAesKey } from '../core/crypto'\nimport { unpackAgent } from '../core/crypto'\nimport { IPFSFetcher } from '../registry/ipfs-fetcher'\nimport type {\n AgentPayload, AgentPrivatePayload,\n EncryptedPayload, SkillDef,\n PackResult, SubscriptionRequired,\n} from '../core/types'\nimport { AgentXError, AgentXErrorCode } from '../core/types'\n\n// ── Injected Dependencies (viem / wagmi integration) ───────────────────────\n\n/** Minimal on-chain reader interface — implement with viem. */\nexport interface OnChainReader {\n /** Read tokenURI from IdentityRegistry by tokenId. */\n getTokenURI(agentId: number): Promise<string>\n /** Get agent metadata attributes (returned as key-value pairs). */\n getAttributes(agentId: number): Promise<Record<string, string>>\n /** Check if `address` has an active subscription for `agentId`. */\n hasActiveSubscription(address: string, agentId: number): Promise<boolean>\n}\n\n/** Minimal wallet signer interface — implement with wagmi/viem. */\nexport interface WalletSigner {\n /** Sign a message (for authentication to MCP servers). */\n signMessage(message: string): Promise<string>\n /** Get the current wallet address. */\n getAddress(): Promise<string>\n /** Get the wallet's ECDSA private key (required for ECIES decryption). */\n getPrivateKey?(): Promise<string>\n}\n\n// ── Agent Runner Configuration ─────────────────────────────────────────────\n\nexport interface AgentRunnerConfig {\n /** On-chain data reader (injected from viem/wagmi). */\n reader: OnChainReader\n /** Wallet signer (injected from wagmi). */\n wallet: WalletSigner\n /** IPFS fetcher instance (creates default if omitted). */\n ipfsFetcher?: IPFSFetcher\n /** IPFS gateway list (overrides IPFSFetcher defaults). */\n ipfsGateways?: string[]\n}\n\n// ── Run Context (returned by useAgent) ─────────────────────────────────────\n\nexport interface AgentRunContext {\n /** Agent NFT token ID */\n agentId: number\n /** System prompt — inject into LLM conversation */\n prompt: string\n /** All skills with execution metadata */\n skills: RunnableSkill[]\n /** MCP connection info */\n mcp: {\n type: string\n url?: string\n toolFilter?: string[]\n }\n /** Subscription expiry timestamp (0 = unknown) */\n subscriptionExpiry: number\n}\n\nexport interface RunnableSkill {\n name: string\n description: string\n inputSchema: Record<string, unknown>\n outputSchema?: Record<string, unknown>\n /** Execution mode */\n mode: 'open' | 'mcp' | 'a2a'\n /** If mode='a2a', the on-chain Agent ID being delegated to */\n a2aTargetAgentId?: number\n /**\n * Execute this skill with the given input.\n * - Open: runs locally (caller provides implementation)\n * - MCP: POSTs to the publisher's MCP server\n * - A2A: loads target Agent context (prompt+skills) via AgentRunner\n */\n execute(input: Record<string, unknown>): Promise<unknown>\n}\n\n// ── A2A Delegation Result ────────────────────────────────────────────────\n\n/**\n * Standard return type for A2A skill execution.\n * The calling LLM receives the sub-Agent's prompt and skills\n * and can inject them into the conversation.\n */\nexport interface A2ASkillResult {\n /** On-chain Agent ID that was delegated to */\n agentId: number\n /** Sub-Agent's decrypted system prompt */\n prompt: string\n /** Sub-Agent's skills (name + description + schema only, no execute) */\n skills: {\n name: string\n description: string\n inputSchema: Record<string, unknown>\n }[]\n /** The original input passed by the caller */\n callerInput: Record<string, unknown>\n}\n\n// ── Agent Runner ───────────────────────────────────────────────────────────\n\nexport class AgentRunner {\n private reader: OnChainReader\n private wallet: WalletSigner\n private ipfs: IPFSFetcher\n\n constructor(config: AgentRunnerConfig) {\n this.reader = config.reader\n this.wallet = config.wallet\n this.ipfs = config.ipfsFetcher ?? new IPFSFetcher({\n fallbackGateways: config.ipfsGateways ?? [\n 'gateway.pinata.cloud',\n 'dweb.link',\n 'cf-ipfs.com',\n ],\n })\n }\n\n // ── Primary API: useAgent ────────────────────────────────────────────────\n\n /**\n * Load and decrypt an Agent, returning a run context ready to inject\n * into any LLM conversation.\n *\n * Steps:\n * 1. Verify on-chain subscription (frontend check)\n * 2. Fetch metadata → get encryptedPayloadCid + eciesEncryptedKey\n * 3. IPFS fetch encrypted payload\n * 4. ECIES decrypt AES key (using wallet private key)\n * 5. AES-256-GCM decrypt payload → { prompt, skills, mcp }\n * 6. Build RunnableSkill wrappers (Open: local stub, Closed: MCP remote)\n */\n async useAgent(agentId: number): Promise<AgentRunContext> {\n // 1. Subscription check (frontend — MCP server also checks)\n const address = await this.wallet.getAddress()\n const isActive = await this.reader.hasActiveSubscription(address, agentId)\n if (!isActive) {\n const err = new AgentXError(\n AgentXErrorCode.NOT_SUBSCRIBED,\n `No active subscription for Agent #${agentId}. ` +\n `Check error.paymentInfo for auto-subscribe via wallet/X402.`,\n )\n ;(err as AgentXError & { paymentInfo: SubscriptionRequired }).paymentInfo = {\n agentId,\n }\n throw err\n }\n\n // 2. Read on-chain metadata\n const attrs = await this.reader.getAttributes(agentId)\n const encryptedPayloadCid = attrs.encryptedPayloadCid\n const eciesEncryptedKey = attrs.eciesEncryptedKey\n\n if (!encryptedPayloadCid || !eciesEncryptedKey) {\n throw new AgentXError(\n AgentXErrorCode.AGENT_NOT_FOUND,\n `Agent #${agentId} metadata incomplete — missing encryptedPayloadCid or eciesEncryptedKey`\n )\n }\n\n // 3. Fetch encrypted payload from IPFS\n let encryptedPayload: EncryptedPayload\n try {\n encryptedPayload = await this.ipfs.fetchEncryptedPayload(encryptedPayloadCid)\n } catch (e) {\n throw new AgentXError(\n AgentXErrorCode.IPFS_FETCH_FAILED,\n `Failed to fetch encrypted payload for agent #${agentId}: ${e}`\n )\n }\n\n // 4 + 5. ECIES + AES decrypt\n let privatePayload: AgentPrivatePayload\n try {\n const privKey = await this._getPrivateKey()\n privatePayload = unpackAgent(encryptedPayload, eciesEncryptedKey, privKey)\n } catch (e) {\n throw new AgentXError(\n AgentXErrorCode.DECRYPTION_FAILED,\n `Failed to decrypt agent #${agentId}: ${e}`\n )\n }\n\n // 6. Build runnable skills\n const skills = privatePayload.skills.map(s => this._wrapSkill(s))\n\n return {\n agentId,\n prompt: privatePayload.prompt,\n skills,\n mcp: {\n type: privatePayload.mcp.type,\n url: privatePayload.mcp.url,\n toolFilter: privatePayload.mcp.toolFilter,\n },\n subscriptionExpiry: 0,\n }\n }\n\n // ── Publishing ───────────────────────────────────────────────────────────\n\n /**\n * Pack an AgentPayload for publishing (encryption only, no IPFS upload).\n * Caller is responsible for IPFS upload and on-chain registration.\n */\n packForPublish(payload: AgentPayload, publicKey: string): PackResult {\n const key = generateAesKey()\n return {\n encryptedCid: '',\n publicCid: '',\n aesKeyHex: key,\n eciesEncryptedKeyHex: eciesEncrypt(key, publicKey),\n }\n }\n\n // ── Internals ────────────────────────────────────────────────────────────\n\n /** Wrap a SkillDef into a RunnableSkill with execute(). */\n private _wrapSkill(skill: SkillDef): RunnableSkill {\n let mode: RunnableSkill['mode'] = 'open'\n let executeFn: (input: Record<string, unknown>) => Promise<unknown>\n\n if (skill.execution) {\n if (skill.execution.type === 'mcp') {\n mode = 'mcp'\n const endpoint = skill.execution.endpoint ?? ''\n const toolName = skill.execution.toolName ?? skill.name\n executeFn = async (input: Record<string, unknown>) => {\n return this._executeMCPTool(endpoint, toolName, input)\n }\n } else if (skill.execution.type === 'a2a') {\n mode = 'a2a'\n executeFn = async (input: Record<string, unknown>) => {\n return this._executeA2ASkill(skill, input)\n }\n } else {\n throw new AgentXError(\n AgentXErrorCode.INVALID_SCHEMA,\n `Unknown execution type \"${(skill.execution as Record<string,string>).type}\" for skill \"${skill.name}\"`\n )\n }\n } else {\n executeFn = async () => {\n throw new AgentXError(\n AgentXErrorCode.INVALID_SCHEMA,\n `Open skill \"${skill.name}\" has no local executor. ` +\n `Implement execute() or switch to execution.type = \"mcp\" or \"a2a\".`\n )\n }\n }\n\n return {\n name: skill.name,\n description: skill.description,\n inputSchema: skill.inputSchema as unknown as Record<string, unknown>,\n outputSchema: skill.outputSchema as unknown as Record<string, unknown>,\n mode,\n execute: executeFn,\n /** If A2A, carry delegation metadata so the LLM can see it */\n a2aTargetAgentId: skill.execution?.type === 'a2a' ? (skill.execution as import('../core/types').A2ASkillExecution).targetAgentId : undefined,\n }\n }\n\n /** Call a tool on the publisher's MCP server (Closed skill). */\n private async _executeMCPTool(\n endpoint: string,\n toolName: string,\n params: Record<string, unknown>\n ): Promise<unknown> {\n const address = await this.wallet.getAddress()\n\n const timestamp = Math.floor(Date.now() / 1000)\n const message = `agentx:mcp:${toolName}:${timestamp}`\n const signature = await this.wallet.signMessage(message)\n\n const res = await fetch(endpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-Subscriber-Address': address,\n 'X-Signature': signature,\n 'X-Timestamp': String(timestamp),\n },\n body: JSON.stringify({\n method: 'tools/call',\n params: {\n name: toolName,\n arguments: params,\n },\n }),\n })\n\n if (!res.ok) {\n const text = await res.text()\n if (res.status === 403) {\n throw new AgentXError(\n AgentXErrorCode.SUBSCRIPTION_EXPIRED,\n `MCP server rejected request: subscription may have expired. ${text}`\n )\n }\n throw new AgentXError(\n AgentXErrorCode.TX_FAILED,\n `MCP tool \"${toolName}\" failed (HTTP ${res.status}): ${text}`\n )\n }\n\n const data = await res.json() as { content?: { type: string; text?: string }[] }\n const content = data.content?.[0]\n if (content?.type === 'text' && content.text) {\n try {\n return JSON.parse(content.text)\n } catch {\n return content.text\n }\n }\n return data\n }\n\n /**\n * Execute an A2A skill — delegate to another AgentX Agent.\n *\n * Standard Interface:\n * Input: { task, ...taskSpecificParams }\n * Output: { agentId, prompt, skills[] }\n *\n * The caller (LLM) receives the sub-Agent's prompt + skill list.\n * The LLM then decides how to use the sub-Agent — typically by\n * injecting the sub-Agent's system prompt and calling its skills.\n */\n private async _executeA2ASkill(\n skill: SkillDef,\n input: Record<string, unknown>\n ): Promise<A2ASkillResult> {\n const exec = skill.execution as import('../core/types').A2ASkillExecution\n if (!exec || exec.type !== 'a2a') {\n throw new AgentXError(\n AgentXErrorCode.INVALID_SCHEMA,\n `Skill \"${skill.name}\" is not an A2A delegation skill`\n )\n }\n\n const targetAgentId = exec.targetAgentId\n\n // Load the target Agent's full context\n let subContext: AgentRunContext\n try {\n subContext = await this.useAgent(targetAgentId)\n } catch (e) {\n throw new AgentXError(\n AgentXErrorCode.AGENT_NOT_FOUND,\n `A2A delegation failed: cannot load Agent #${targetAgentId}. ${e}`\n )\n }\n\n // Apply skill filter if specified\n if (exec.skillFilter && exec.skillFilter.length > 0) {\n const filterSet = new Set(exec.skillFilter)\n subContext = {\n ...subContext,\n skills: subContext.skills.filter(s => filterSet.has(s.name)),\n }\n }\n\n // Apply prompt override if specified\n if (exec.promptOverride) {\n subContext = { ...subContext, prompt: exec.promptOverride }\n }\n\n return {\n agentId: targetAgentId,\n prompt: subContext.prompt,\n skills: subContext.skills.map(s => ({\n name: s.name,\n description: s.description,\n inputSchema: s.inputSchema,\n })),\n // Pass the caller's input to the sub-agent's context\n callerInput: input,\n }\n }\n\n private async _getPrivateKey(): Promise<string> {\n if (this.wallet.getPrivateKey) return this.wallet.getPrivateKey()\n throw new AgentXError(\n AgentXErrorCode.WALLET_NOT_CONNECTED,\n 'Wallet must support getPrivateKey() for ECIES decryption.'\n )\n }\n}\n","// ---------------------------------------------------------------------------\n// @agentx/sdk — Configuration\n// ---------------------------------------------------------------------------\n// Wraps ConfigurationRegistry contract for key-value settings.\n// ---------------------------------------------------------------------------\n\nimport { stringToHex, hexToString } from 'viem'\nimport type { PublicClient, WalletClient, Address, Hash } from 'viem'\n\nconst CONFIG_ABI = {\n setConfig: {\n inputs: [{ name: 'key', type: 'string' }, { name: 'value', type: 'bytes' }] as const,\n name: 'setConfig' as const,\n outputs: [] as const,\n stateMutability: 'nonpayable' as const,\n type: 'function' as const,\n },\n getConfig: {\n inputs: [{ name: 'key', type: 'string' }] as const,\n name: 'getConfig' as const,\n outputs: [{ name: '', type: 'bytes' }] as const,\n stateMutability: 'view' as const,\n type: 'function' as const,\n },\n getAllConfig: {\n inputs: [] as const,\n name: 'getAllConfig' as const,\n outputs: [{ name: '', type: 'tuple[]', components: [{ name: 'key', type: 'string' }, { name: 'value', type: 'bytes' }] }] as const,\n stateMutability: 'view' as const,\n type: 'function' as const,\n },\n} as const\n\n// ── Known chain configs ────────────────────────────────────────────────────\n\n// Moves these to a separate file when the list grows.\n\nexport interface ChainConfig {\n chainId: number\n contracts: {\n identityRegistry: Address\n subscriptionManager: Address\n paymentGateway: Address\n a2aProtocolRegistry: Address\n reputationRegistry: Address\n configurationRegistry: Address\n }\n ipfsGateways: string[]\n rpcUrl?: string\n}\n\nexport const KNOWN_CHAINS: Record<number, ChainConfig> = {\n // Sepolia Testnet\n // v3 (deployed 2026-07-13): platformFee=250bps(2.5%), ReentrancyGuard, audit fixes\n 11155111: {\n chainId: 11155111,\n contracts: {\n identityRegistry: '0xe94ad380d3F8d08a7590eda0C84f354a93F96e5F',\n subscriptionManager: '0xC15fE80b9d800abb72121F353a6ae6d6E9077E63',\n paymentGateway: '0x59eA58c0089314C0fCc86A4ff646fb6dAE571C96',\n a2aProtocolRegistry: '0xEdb0022c250B38e281B3EF1418037889fC5C6092',\n reputationRegistry: '0xeb6B410ea71b8d9dA0c96f6A91d35027CE143DC9',\n configurationRegistry: '0x68DcE00e4C9077c94BC68016cD14B09557faEA6c',\n },\n ipfsGateways: ['ipfs.io', 'gateway.pinata.cloud', 'dweb.link', 'cf-ipfs.com'],\n },\n\n // OxaChain L1 Mainnet\n // Chain ID 19505, Clique PoA, Shanghai+Cancun, gas token T0x\n // Deployer: 0x8E869A0624fF9e766Df71b5B08897d00E4d260ba\n // RPC: http://43.156.99.215:18545\n // Explorer: http://43.156.99.215:18400\n // All 6 core contracts deployed 2026-07-14\n 19505: {\n chainId: 19505,\n contracts: {\n identityRegistry: '0xbf5F9db266c8c97E3334466C88597Eb758AfE212',\n subscriptionManager: '0x019AC9d945467478Dd371CDbD70cb2f325800E6B',\n paymentGateway: '0x0000000000000000000000000000000000000000',\n a2aProtocolRegistry: '0x61b7E7Eed21F013e35a90FC5de5c352780ec5169',\n reputationRegistry: '0x6a18C2664E1b42063860d864b6448b824d7B843F',\n configurationRegistry: '0x07280674ccc2898Fd038A9e3C22005CA83ffD2F8',\n },\n ipfsGateways: ['ipfs.io', 'gateway.pinata.cloud', 'dweb.link', 'cf-ipfs.com'],\n rpcUrl: 'http://43.156.99.215:18545',\n },\n}\n\n// ── Config Registry ────────────────────────────────────────────────────────\n\nexport interface ConfigRegistryOpts {\n contractAddress: Address\n publicClient: PublicClient\n walletClient: WalletClient\n}\n\nexport class ConfigurationRegistry {\n private address: Address\n private publicClient: PublicClient\n private walletClient: WalletClient\n\n constructor(opts: ConfigRegistryOpts) {\n this.address = opts.contractAddress\n this.publicClient = opts.publicClient\n this.walletClient = opts.walletClient\n }\n\n private get account(): Promise<Address> {\n return this.walletClient.getAddresses().then(a => {\n if (!a[0]) throw new Error('Wallet not connected')\n return a[0]\n })\n }\n\n async set(key: string, value: string): Promise<Hash> {\n const acct = await this.account\n const { request } = await this.publicClient.simulateContract({\n account: acct,\n address: this.address,\n abi: [CONFIG_ABI.setConfig],\n functionName: 'setConfig',\n args: [key, stringToHex(value)],\n })\n return this.walletClient.writeContract(request)\n }\n\n async get(key: string): Promise<string> {\n const r = await this.publicClient.readContract({\n address: this.address,\n abi: [CONFIG_ABI.getConfig],\n functionName: 'getConfig',\n args: [key],\n })\n return hexToString(r as `0x${string}`)\n }\n\n async getAll(): Promise<Record<string, string>> {\n const r = await this.publicClient.readContract({\n address: this.address,\n abi: [CONFIG_ABI.getAllConfig],\n functionName: 'getAllConfig',\n })\n const map: Record<string, string> = {}\n for (const { key, value } of r as { key: string; value: string }[]) {\n map[key] = hexToString(value as `0x${string}`)\n }\n return map\n }\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentxv2/sdk",
3
- "version": "0.3.1",
3
+ "version": "0.5.0",
4
4
  "description": "AgentX — Decentralized AI Agent SDK with ECIES + AES-256-GCM encryption",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.mts",