@agentxv2/sdk 0.3.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. package/README.md +11 -11
  2. package/dist/core.d.mts +64 -0
  3. package/dist/core.d.ts +64 -0
  4. package/dist/core.js +275 -0
  5. package/dist/core.js.map +1 -0
  6. package/dist/core.mjs +240 -0
  7. package/dist/core.mjs.map +1 -0
  8. package/dist/{agent/agent-runner.d.ts → index-DhXVi_ub.d.ts} +94 -10
  9. package/dist/index-eQO4iaOr.d.mts +208 -0
  10. package/dist/index.d.mts +269 -0
  11. package/dist/index.d.ts +269 -10
  12. package/dist/index.js +2398 -31
  13. package/dist/index.js.map +1 -1
  14. package/dist/index.mjs +2345 -0
  15. package/dist/index.mjs.map +1 -0
  16. package/dist/react.d.mts +3 -0
  17. package/dist/react.d.ts +3 -0
  18. package/dist/react.js +737 -0
  19. package/dist/react.js.map +1 -0
  20. package/dist/react.mjs +717 -0
  21. package/dist/react.mjs.map +1 -0
  22. package/dist/{core/types.d.ts → types-2aHUvS4M.d.mts} +34 -33
  23. package/dist/types-2aHUvS4M.d.ts +297 -0
  24. package/package.json +12 -11
  25. package/dist/a2a/a2a.d.ts +0 -37
  26. package/dist/a2a/a2a.d.ts.map +0 -1
  27. package/dist/a2a/a2a.js +0 -252
  28. package/dist/a2a/a2a.js.map +0 -1
  29. package/dist/a2a/index.d.ts +0 -4
  30. package/dist/a2a/index.d.ts.map +0 -1
  31. package/dist/a2a/index.js +0 -4
  32. package/dist/a2a/index.js.map +0 -1
  33. package/dist/agent/agent-runner.d.ts.map +0 -1
  34. package/dist/agent/agent-runner.js +0 -249
  35. package/dist/agent/agent-runner.js.map +0 -1
  36. package/dist/agent/index.d.ts +0 -3
  37. package/dist/agent/index.d.ts.map +0 -1
  38. package/dist/agent/index.js +0 -3
  39. package/dist/agent/index.js.map +0 -1
  40. package/dist/config/config.d.ts +0 -31
  41. package/dist/config/config.d.ts.map +0 -1
  42. package/dist/config/config.js +0 -95
  43. package/dist/config/config.js.map +0 -1
  44. package/dist/config/index.d.ts +0 -4
  45. package/dist/config/index.d.ts.map +0 -1
  46. package/dist/config/index.js +0 -4
  47. package/dist/config/index.js.map +0 -1
  48. package/dist/core/crypto.d.ts +0 -62
  49. package/dist/core/crypto.d.ts.map +0 -1
  50. package/dist/core/crypto.js +0 -291
  51. package/dist/core/crypto.js.map +0 -1
  52. package/dist/core/index.d.ts +0 -3
  53. package/dist/core/index.d.ts.map +0 -1
  54. package/dist/core/index.js +0 -4
  55. package/dist/core/index.js.map +0 -1
  56. package/dist/core/types.d.ts.map +0 -1
  57. package/dist/core/types.js +0 -30
  58. package/dist/core/types.js.map +0 -1
  59. package/dist/index.d.ts.map +0 -1
  60. package/dist/mcp/connector.d.ts +0 -43
  61. package/dist/mcp/connector.d.ts.map +0 -1
  62. package/dist/mcp/connector.js +0 -79
  63. package/dist/mcp/connector.js.map +0 -1
  64. package/dist/mcp/index.d.ts +0 -4
  65. package/dist/mcp/index.d.ts.map +0 -1
  66. package/dist/mcp/index.js +0 -4
  67. package/dist/mcp/index.js.map +0 -1
  68. package/dist/react/index.d.ts +0 -4
  69. package/dist/react/index.d.ts.map +0 -1
  70. package/dist/react/index.js +0 -3
  71. package/dist/react/index.js.map +0 -1
  72. package/dist/react/useAgentRunner.d.ts +0 -16
  73. package/dist/react/useAgentRunner.d.ts.map +0 -1
  74. package/dist/react/useAgentRunner.js +0 -204
  75. package/dist/react/useAgentRunner.js.map +0 -1
  76. package/dist/registry/agent-registry.d.ts +0 -52
  77. package/dist/registry/agent-registry.d.ts.map +0 -1
  78. package/dist/registry/agent-registry.js +0 -221
  79. package/dist/registry/agent-registry.js.map +0 -1
  80. package/dist/registry/index.d.ts +0 -7
  81. package/dist/registry/index.d.ts.map +0 -1
  82. package/dist/registry/index.js +0 -6
  83. package/dist/registry/index.js.map +0 -1
  84. package/dist/registry/ipfs-fetcher.d.ts +0 -39
  85. package/dist/registry/ipfs-fetcher.d.ts.map +0 -1
  86. package/dist/registry/ipfs-fetcher.js +0 -139
  87. package/dist/registry/ipfs-fetcher.js.map +0 -1
  88. package/dist/reputation/index.d.ts +0 -4
  89. package/dist/reputation/index.d.ts.map +0 -1
  90. package/dist/reputation/index.js +0 -4
  91. package/dist/reputation/index.js.map +0 -1
  92. package/dist/reputation/reputation.d.ts +0 -26
  93. package/dist/reputation/reputation.d.ts.map +0 -1
  94. package/dist/reputation/reputation.js +0 -113
  95. package/dist/reputation/reputation.js.map +0 -1
  96. package/dist/subscription/agent-x402.d.ts +0 -33
  97. package/dist/subscription/agent-x402.d.ts.map +0 -1
  98. package/dist/subscription/agent-x402.js +0 -144
  99. package/dist/subscription/agent-x402.js.map +0 -1
  100. package/dist/subscription/index.d.ts +0 -6
  101. package/dist/subscription/index.d.ts.map +0 -1
  102. package/dist/subscription/index.js +0 -5
  103. package/dist/subscription/index.js.map +0 -1
  104. package/dist/subscription/subscription.d.ts +0 -67
  105. package/dist/subscription/subscription.d.ts.map +0 -1
  106. package/dist/subscription/subscription.js +0 -346
  107. package/dist/subscription/subscription.js.map +0 -1
package/dist/react.js ADDED
@@ -0,0 +1,737 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/react/index.ts
21
+ var react_exports = {};
22
+ __export(react_exports, {
23
+ useAgentRunner: () => useAgentRunner
24
+ });
25
+ module.exports = __toCommonJS(react_exports);
26
+
27
+ // src/react/useAgentRunner.ts
28
+ var import_react = require("react");
29
+ var import_wagmi = require("wagmi");
30
+
31
+ // src/core/crypto.ts
32
+ var import_aes = require("@noble/ciphers/aes.js");
33
+ var import_secp256k1 = require("@noble/curves/secp256k1.js");
34
+ var import_sha2 = require("@noble/hashes/sha2.js");
35
+ var import_hkdf = require("@noble/hashes/hkdf.js");
36
+ var import_hmac = require("@noble/hashes/hmac.js");
37
+ var import_utils = require("@noble/ciphers/utils.js");
38
+ function randomBytes(length) {
39
+ if (typeof crypto !== "undefined" && crypto.getRandomValues) {
40
+ const buf = new Uint8Array(length);
41
+ crypto.getRandomValues(buf);
42
+ return buf;
43
+ }
44
+ const nodeCrypto = require("crypto");
45
+ return new Uint8Array(nodeCrypto.randomBytes(length));
46
+ }
47
+ var AES_KEY_SIZE = 32;
48
+ var IV_SIZE = 12;
49
+ var TAG_SIZE = 16;
50
+ function fromBase64(b64) {
51
+ if (typeof Buffer !== "undefined") return new Uint8Array(Buffer.from(b64, "base64"));
52
+ const binary = atob(b64);
53
+ const bytes = new Uint8Array(binary.length);
54
+ for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
55
+ return bytes;
56
+ }
57
+ function aesDecrypt(encryptedBase64, keyHex) {
58
+ const key = (0, import_utils.hexToBytes)(keyHex);
59
+ const combined = fromBase64(encryptedBase64);
60
+ const iv = combined.subarray(0, IV_SIZE);
61
+ const ciphertext = combined.subarray(IV_SIZE, -TAG_SIZE);
62
+ const authTag = combined.subarray(-TAG_SIZE);
63
+ const cipher = (0, import_aes.gcm)(key, iv);
64
+ const ciphertextWithTag = new Uint8Array(ciphertext.length + TAG_SIZE);
65
+ ciphertextWithTag.set(ciphertext, 0);
66
+ ciphertextWithTag.set(authTag, ciphertext.length);
67
+ const decrypted = cipher.decrypt(ciphertextWithTag);
68
+ return new TextDecoder().decode(decrypted);
69
+ }
70
+ function generateAesKey() {
71
+ return (0, import_utils.bytesToHex)(randomBytes(AES_KEY_SIZE));
72
+ }
73
+ function eciesEncode(ephemeralPub, iv, ciphertext, mac) {
74
+ const out = new Uint8Array(33 + 16 + ciphertext.length + 32);
75
+ out.set(ephemeralPub, 0);
76
+ out.set(iv, 33);
77
+ out.set(ciphertext, 33 + 16);
78
+ out.set(mac, 33 + 16 + ciphertext.length);
79
+ return (0, import_utils.bytesToHex)(out);
80
+ }
81
+ function eciesDecode(dataHex) {
82
+ const d = (0, import_utils.hexToBytes)(dataHex);
83
+ return {
84
+ ephemeralPub: d.subarray(0, 33),
85
+ iv: d.subarray(33, 49),
86
+ ciphertext: d.subarray(49, -32),
87
+ mac: d.subarray(-32)
88
+ };
89
+ }
90
+ function aesCtrEncrypt(key, ctrBytes, data) {
91
+ const blockSize = 16;
92
+ const cipher = (0, import_aes.gcm)(key, ctrBytes);
93
+ const result = new Uint8Array(data.length);
94
+ const counter = new Uint8Array(blockSize);
95
+ counter.set(ctrBytes);
96
+ for (let i = 0; i < data.length; i += blockSize) {
97
+ const keystream = (0, import_aes.gcm)(key, counter).encrypt(new Uint8Array(blockSize));
98
+ for (let j = 0; j < blockSize && i + j < data.length; j++) {
99
+ result[i + j] = keystream[j] ^ data[i + j];
100
+ }
101
+ for (let j = blockSize - 1; j >= 0; j--) {
102
+ const val = counter[j];
103
+ if (val !== void 0) {
104
+ counter[j] = val + 1 & 255;
105
+ if (counter[j] !== 0) break;
106
+ }
107
+ }
108
+ }
109
+ return result;
110
+ }
111
+ function eciesEncrypt(dataHex, publicKey) {
112
+ const ephPriv = randomBytes(32);
113
+ const ephPub = import_secp256k1.secp256k1.getPublicKey(ephPriv, true);
114
+ let recipientPub;
115
+ if (publicKey.startsWith("04") && publicKey.length === 130) {
116
+ recipientPub = (0, import_utils.hexToBytes)(publicKey);
117
+ } else if (publicKey.startsWith("02") || publicKey.startsWith("03")) {
118
+ recipientPub = (0, import_utils.hexToBytes)(publicKey);
119
+ } else {
120
+ throw new Error("Invalid public key format: expected hex with 02/03/04 prefix");
121
+ }
122
+ const shared = import_secp256k1.secp256k1.getSharedSecret(ephPriv, recipientPub);
123
+ const sharedX = shared.subarray(1, 33);
124
+ const sharedKey = (0, import_sha2.sha256)(sharedX);
125
+ const hkdfOut = (0, import_hkdf.hkdf)(import_sha2.sha256, sharedKey, void 0, void 0, 64);
126
+ const encKey = hkdfOut.subarray(0, 32);
127
+ const macKey = hkdfOut.subarray(32, 64);
128
+ const iv = randomBytes(16);
129
+ const plaintext = (0, import_utils.hexToBytes)(dataHex);
130
+ const ciphertext = aesCtrEncrypt(encKey, iv, plaintext);
131
+ const macInput = new Uint8Array(33 + 16 + ciphertext.length);
132
+ macInput.set(ephPub, 0);
133
+ macInput.set(iv, 33);
134
+ macInput.set(ciphertext, 33 + 16);
135
+ const mac = (0, import_hmac.hmac)(import_sha2.sha256, macKey, macInput);
136
+ return eciesEncode(ephPub, iv, ciphertext, mac);
137
+ }
138
+ function eciesDecrypt(dataHex, privateKey) {
139
+ const { ephemeralPub, iv, ciphertext, mac } = eciesDecode(dataHex);
140
+ const privBytes = (0, import_utils.hexToBytes)(privateKey);
141
+ const shared = import_secp256k1.secp256k1.getSharedSecret(privBytes, ephemeralPub);
142
+ const sharedX = shared.subarray(1, 33);
143
+ const sharedKey = (0, import_sha2.sha256)(sharedX);
144
+ const hkdfOut = (0, import_hkdf.hkdf)(import_sha2.sha256, sharedKey, void 0, void 0, 64);
145
+ const encKey = hkdfOut.subarray(0, 32);
146
+ const macKey = hkdfOut.subarray(32, 64);
147
+ const macInput = new Uint8Array(33 + 16 + ciphertext.length);
148
+ macInput.set(ephemeralPub, 0);
149
+ macInput.set(iv, 33);
150
+ macInput.set(ciphertext, 33 + 16);
151
+ const expectedMac = (0, import_hmac.hmac)(import_sha2.sha256, macKey, macInput);
152
+ if (!constantTimeEqual(mac, expectedMac)) {
153
+ throw new Error("ECIES decryption failed: MAC mismatch");
154
+ }
155
+ const plaintext = aesCtrEncrypt(encKey, iv, ciphertext);
156
+ return (0, import_utils.bytesToHex)(plaintext);
157
+ }
158
+ function constantTimeEqual(a, b) {
159
+ if (a.length !== b.length) return false;
160
+ let diff = 0;
161
+ for (let i = 0; i < a.length; i++) diff |= a[i] ^ b[i];
162
+ return diff === 0;
163
+ }
164
+ function decryptPayload(encrypted, keyHex) {
165
+ if (encrypted.algorithm !== "AES-256-GCM") {
166
+ throw new Error(`Unsupported algorithm: ${encrypted.algorithm}`);
167
+ }
168
+ return JSON.parse(aesDecrypt(encrypted.data, keyHex));
169
+ }
170
+ function unpackAgent(encryptedPayload, eciesEncryptedKey, privateKey) {
171
+ const aesKeyHex = eciesDecrypt(eciesEncryptedKey, privateKey);
172
+ return decryptPayload(encryptedPayload, aesKeyHex);
173
+ }
174
+
175
+ // src/registry/ipfs-fetcher.ts
176
+ var IPFSFetcher = class {
177
+ gateway;
178
+ fallbackGateways;
179
+ timeoutMs;
180
+ cache = /* @__PURE__ */ new Map();
181
+ maxCache;
182
+ pending = /* @__PURE__ */ new Map();
183
+ failed = /* @__PURE__ */ new Set();
184
+ constructor(config = {}) {
185
+ this.gateway = config.gateway ?? "ipfs.io";
186
+ this.fallbackGateways = config.fallbackGateways ?? [
187
+ "gateway.pinata.cloud",
188
+ "dweb.link",
189
+ "cf-ipfs.com"
190
+ ];
191
+ this.timeoutMs = config.timeoutMs ?? 1e4;
192
+ this.maxCache = config.maxCache ?? 200;
193
+ }
194
+ // ── Public API ──────────────────────────────────────────────────────────
195
+ /** Fetch JSON from a single IPFS CID. */
196
+ async fetchJSON(cid) {
197
+ const cached = this.cache.get(cid);
198
+ if (cached) return cached.data;
199
+ if (this.failed.has(cid)) throw new Error(`CID ${cid} previously failed`);
200
+ const pending = this.pending.get(cid);
201
+ if (pending) return pending;
202
+ const promise = this._doFetch(cid);
203
+ this.pending.set(cid, promise);
204
+ try {
205
+ const data = await promise;
206
+ this._cacheSet(cid, data);
207
+ return data;
208
+ } catch (e) {
209
+ this.failed.add(cid);
210
+ throw e;
211
+ } finally {
212
+ this.pending.delete(cid);
213
+ }
214
+ }
215
+ /** Fetch encrypted agent payload (validates algorithm). */
216
+ async fetchEncryptedPayload(cid) {
217
+ const raw = await this.fetchJSON(cid);
218
+ if (!raw.encrypted || raw.algorithm !== "AES-256-GCM" || typeof raw.data !== "string") {
219
+ throw new Error(`Invalid EncryptedPayload at CID ${cid}`);
220
+ }
221
+ return raw;
222
+ }
223
+ /** Batch fetch multiple CIDs with concurrency control. */
224
+ async fetchBatch(cids, concurrency = 5) {
225
+ const results = /* @__PURE__ */ new Map();
226
+ const unique = [...new Set(cids)].filter((c) => this.isValidCID(c));
227
+ for (let i = 0; i < unique.length; i += concurrency) {
228
+ const batch = unique.slice(i, i + concurrency);
229
+ const settled = await Promise.allSettled(
230
+ batch.map((cid) => this.fetchJSON(cid))
231
+ );
232
+ settled.forEach((r, j) => {
233
+ if (r.status === "fulfilled") results.set(batch[j], r.value);
234
+ });
235
+ if (i + concurrency < unique.length) {
236
+ await new Promise((r) => setTimeout(r, 200));
237
+ }
238
+ }
239
+ return results;
240
+ }
241
+ /** Check if a string looks like a valid IPFS CID. */
242
+ isValidCID(cid) {
243
+ return /^(Qm[1-9A-HJ-NP-Za-km-z]{44,}|b[a-z2-7]{58,}|[A-Za-z0-9+/]{46,})$/.test(cid);
244
+ }
245
+ /** Clear cache (optionally for a specific CID). */
246
+ clearCache(cid) {
247
+ if (cid) {
248
+ this.cache.delete(cid);
249
+ } else {
250
+ this.cache.clear();
251
+ }
252
+ this.failed.clear();
253
+ }
254
+ /** Number of cached entries. */
255
+ get cacheSize() {
256
+ return this.cache.size;
257
+ }
258
+ // ── Internal ─────────────────────────────────────────────────────────────
259
+ async _doFetch(cid) {
260
+ if (!this.isValidCID(cid)) throw new Error(`Invalid CID: ${cid}`);
261
+ try {
262
+ return await this._fetchFrom(cid, this.gateway, this.timeoutMs);
263
+ } catch {
264
+ }
265
+ for (const gw of this.fallbackGateways) {
266
+ try {
267
+ return await this._fetchFrom(cid, gw, this.timeoutMs);
268
+ } catch {
269
+ }
270
+ }
271
+ throw new Error(`All IPFS gateways failed for CID ${cid}`);
272
+ }
273
+ async _fetchFrom(cid, gateway, timeoutMs) {
274
+ const url = `https://${gateway}/ipfs/${cid}`;
275
+ const res = await fetch(url, {
276
+ headers: { Accept: "application/json" },
277
+ signal: AbortSignal.timeout(timeoutMs)
278
+ });
279
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
280
+ return await res.json();
281
+ }
282
+ _cacheSet(cid, data) {
283
+ this.cache.set(cid, { data, timestamp: Date.now() });
284
+ if (this.cache.size > this.maxCache) {
285
+ const oldest = [...this.cache.entries()].sort(
286
+ (a, b) => a[1].timestamp - b[1].timestamp
287
+ )[0];
288
+ if (oldest) this.cache.delete(oldest[0]);
289
+ }
290
+ }
291
+ };
292
+ var defaultIPFSFetcher = new IPFSFetcher();
293
+
294
+ // src/core/types.ts
295
+ var AgentXError = class extends Error {
296
+ code;
297
+ /** If NOT_SUBSCRIBED, carry enough info for wallet/X402 auto-payment */
298
+ paymentInfo;
299
+ constructor(code, message) {
300
+ super(message);
301
+ this.code = code;
302
+ this.name = "AgentXError";
303
+ }
304
+ };
305
+
306
+ // src/agent/agent-runner.ts
307
+ var AgentRunner = class {
308
+ reader;
309
+ wallet;
310
+ ipfs;
311
+ constructor(config) {
312
+ this.reader = config.reader;
313
+ this.wallet = config.wallet;
314
+ this.ipfs = config.ipfsFetcher ?? new IPFSFetcher({
315
+ fallbackGateways: config.ipfsGateways ?? [
316
+ "gateway.pinata.cloud",
317
+ "dweb.link",
318
+ "cf-ipfs.com"
319
+ ]
320
+ });
321
+ }
322
+ // ── Primary API: useAgent ────────────────────────────────────────────────
323
+ /**
324
+ * Load and decrypt an Agent, returning a run context ready to inject
325
+ * into any LLM conversation.
326
+ *
327
+ * Steps:
328
+ * 1. Verify on-chain subscription (frontend check)
329
+ * 2. Fetch metadata → get encryptedPayloadCid + eciesEncryptedKey
330
+ * 3. IPFS fetch encrypted payload
331
+ * 4. ECIES decrypt AES key (using wallet private key)
332
+ * 5. AES-256-GCM decrypt payload → { prompt, skills, mcp }
333
+ * 6. Build RunnableSkill wrappers (Open: local stub, Closed: MCP remote)
334
+ */
335
+ async useAgent(agentId) {
336
+ const address = await this.wallet.getAddress();
337
+ const isActive = await this.reader.hasActiveSubscription(address, agentId);
338
+ if (!isActive) {
339
+ const err = new AgentXError(
340
+ "NOT_SUBSCRIBED" /* NOT_SUBSCRIBED */,
341
+ `No active subscription for Agent #${agentId}. Check error.paymentInfo for auto-subscribe via wallet/X402.`
342
+ );
343
+ err.paymentInfo = {
344
+ agentId
345
+ };
346
+ throw err;
347
+ }
348
+ const attrs = await this.reader.getAttributes(agentId);
349
+ const encryptedPayloadCid = attrs.encryptedPayloadCid;
350
+ const eciesEncryptedKey = attrs.eciesEncryptedKey;
351
+ if (!encryptedPayloadCid || !eciesEncryptedKey) {
352
+ throw new AgentXError(
353
+ "AGENT_NOT_FOUND" /* AGENT_NOT_FOUND */,
354
+ `Agent #${agentId} metadata incomplete \u2014 missing encryptedPayloadCid or eciesEncryptedKey`
355
+ );
356
+ }
357
+ let encryptedPayload;
358
+ try {
359
+ encryptedPayload = await this.ipfs.fetchEncryptedPayload(encryptedPayloadCid);
360
+ } catch (e) {
361
+ throw new AgentXError(
362
+ "IPFS_FETCH_FAILED" /* IPFS_FETCH_FAILED */,
363
+ `Failed to fetch encrypted payload for agent #${agentId}: ${e}`
364
+ );
365
+ }
366
+ let privatePayload;
367
+ try {
368
+ const privKey = await this._getPrivateKey();
369
+ privatePayload = unpackAgent(encryptedPayload, eciesEncryptedKey, privKey);
370
+ } catch (e) {
371
+ throw new AgentXError(
372
+ "DECRYPTION_FAILED" /* DECRYPTION_FAILED */,
373
+ `Failed to decrypt agent #${agentId}: ${e}`
374
+ );
375
+ }
376
+ const skills = privatePayload.skills.map((s) => this._wrapSkill(s));
377
+ return {
378
+ agentId,
379
+ prompt: privatePayload.prompt,
380
+ skills,
381
+ mcp: {
382
+ type: privatePayload.mcp.type,
383
+ url: privatePayload.mcp.url,
384
+ toolFilter: privatePayload.mcp.toolFilter
385
+ },
386
+ subscriptionExpiry: 0
387
+ };
388
+ }
389
+ // ── Publishing ───────────────────────────────────────────────────────────
390
+ /**
391
+ * Pack an AgentPayload for publishing (encryption only, no IPFS upload).
392
+ * Caller is responsible for IPFS upload and on-chain registration.
393
+ */
394
+ packForPublish(payload, publicKey) {
395
+ const key = generateAesKey();
396
+ return {
397
+ encryptedCid: "",
398
+ publicCid: "",
399
+ aesKeyHex: key,
400
+ eciesEncryptedKeyHex: eciesEncrypt(key, publicKey)
401
+ };
402
+ }
403
+ // ── Internals ────────────────────────────────────────────────────────────
404
+ /** Wrap a SkillDef into a RunnableSkill with execute(). */
405
+ _wrapSkill(skill) {
406
+ let mode = "open";
407
+ let executeFn;
408
+ if (skill.execution) {
409
+ if (skill.execution.type === "mcp") {
410
+ mode = "mcp";
411
+ const endpoint = skill.execution.endpoint ?? "";
412
+ const toolName = skill.execution.toolName ?? skill.name;
413
+ executeFn = async (input) => {
414
+ return this._executeMCPTool(endpoint, toolName, input);
415
+ };
416
+ } else if (skill.execution.type === "a2a") {
417
+ mode = "a2a";
418
+ executeFn = async (input) => {
419
+ return this._executeA2ASkill(skill, input);
420
+ };
421
+ } else {
422
+ throw new AgentXError(
423
+ "INVALID_SCHEMA" /* INVALID_SCHEMA */,
424
+ `Unknown execution type "${skill.execution.type}" for skill "${skill.name}"`
425
+ );
426
+ }
427
+ } else {
428
+ executeFn = async () => {
429
+ throw new AgentXError(
430
+ "INVALID_SCHEMA" /* INVALID_SCHEMA */,
431
+ `Open skill "${skill.name}" has no local executor. Implement execute() or switch to execution.type = "mcp" or "a2a".`
432
+ );
433
+ };
434
+ }
435
+ return {
436
+ name: skill.name,
437
+ description: skill.description,
438
+ inputSchema: skill.inputSchema,
439
+ outputSchema: skill.outputSchema,
440
+ mode,
441
+ execute: executeFn,
442
+ /** If A2A, carry delegation metadata so the LLM can see it */
443
+ a2aTargetAgentId: skill.execution?.type === "a2a" ? skill.execution.targetAgentId : void 0
444
+ };
445
+ }
446
+ /** Call a tool on the publisher's MCP server (Closed skill). */
447
+ async _executeMCPTool(endpoint, toolName, params) {
448
+ const address = await this.wallet.getAddress();
449
+ const timestamp = Math.floor(Date.now() / 1e3);
450
+ const message = `agentx:mcp:${toolName}:${timestamp}`;
451
+ const signature = await this.wallet.signMessage(message);
452
+ const res = await fetch(endpoint, {
453
+ method: "POST",
454
+ headers: {
455
+ "Content-Type": "application/json",
456
+ "X-Subscriber-Address": address,
457
+ "X-Signature": signature,
458
+ "X-Timestamp": String(timestamp)
459
+ },
460
+ body: JSON.stringify({
461
+ method: "tools/call",
462
+ params: {
463
+ name: toolName,
464
+ arguments: params
465
+ }
466
+ })
467
+ });
468
+ if (!res.ok) {
469
+ const text = await res.text();
470
+ if (res.status === 403) {
471
+ throw new AgentXError(
472
+ "SUBSCRIPTION_EXPIRED" /* SUBSCRIPTION_EXPIRED */,
473
+ `MCP server rejected request: subscription may have expired. ${text}`
474
+ );
475
+ }
476
+ throw new AgentXError(
477
+ "TX_FAILED" /* TX_FAILED */,
478
+ `MCP tool "${toolName}" failed (HTTP ${res.status}): ${text}`
479
+ );
480
+ }
481
+ const data = await res.json();
482
+ const content = data.content?.[0];
483
+ if (content?.type === "text" && content.text) {
484
+ try {
485
+ return JSON.parse(content.text);
486
+ } catch {
487
+ return content.text;
488
+ }
489
+ }
490
+ return data;
491
+ }
492
+ /**
493
+ * Execute an A2A skill — delegate to another AgentX Agent.
494
+ *
495
+ * Standard Interface:
496
+ * Input: { task, ...taskSpecificParams }
497
+ * Output: { agentId, prompt, skills[] }
498
+ *
499
+ * The caller (LLM) receives the sub-Agent's prompt + skill list.
500
+ * The LLM then decides how to use the sub-Agent — typically by
501
+ * injecting the sub-Agent's system prompt and calling its skills.
502
+ */
503
+ async _executeA2ASkill(skill, input) {
504
+ const exec = skill.execution;
505
+ if (!exec || exec.type !== "a2a") {
506
+ throw new AgentXError(
507
+ "INVALID_SCHEMA" /* INVALID_SCHEMA */,
508
+ `Skill "${skill.name}" is not an A2A delegation skill`
509
+ );
510
+ }
511
+ const targetAgentId = exec.targetAgentId;
512
+ let subContext;
513
+ try {
514
+ subContext = await this.useAgent(targetAgentId);
515
+ } catch (e) {
516
+ throw new AgentXError(
517
+ "AGENT_NOT_FOUND" /* AGENT_NOT_FOUND */,
518
+ `A2A delegation failed: cannot load Agent #${targetAgentId}. ${e}`
519
+ );
520
+ }
521
+ if (exec.skillFilter && exec.skillFilter.length > 0) {
522
+ const filterSet = new Set(exec.skillFilter);
523
+ subContext = {
524
+ ...subContext,
525
+ skills: subContext.skills.filter((s) => filterSet.has(s.name))
526
+ };
527
+ }
528
+ if (exec.promptOverride) {
529
+ subContext = { ...subContext, prompt: exec.promptOverride };
530
+ }
531
+ return {
532
+ agentId: targetAgentId,
533
+ prompt: subContext.prompt,
534
+ skills: subContext.skills.map((s) => ({
535
+ name: s.name,
536
+ description: s.description,
537
+ inputSchema: s.inputSchema
538
+ })),
539
+ // Pass the caller's input to the sub-agent's context
540
+ callerInput: input
541
+ };
542
+ }
543
+ async _getPrivateKey() {
544
+ if (this.wallet.getPrivateKey) return this.wallet.getPrivateKey();
545
+ throw new AgentXError(
546
+ "WALLET_NOT_CONNECTED" /* WALLET_NOT_CONNECTED */,
547
+ "Wallet must support getPrivateKey() for ECIES decryption."
548
+ );
549
+ }
550
+ };
551
+
552
+ // src/config/config.ts
553
+ var KNOWN_CHAINS = {
554
+ // Sepolia
555
+ // Sepolia v2 (deployed 2026-07-13): platformFee=500bps(5%), multi-currency, trial escrow
556
+ 11155111: {
557
+ chainId: 11155111,
558
+ contracts: {
559
+ identityRegistry: "0xe94ad380d3F8d08a7590eda0C84f354a93F96e5F",
560
+ subscriptionManager: "0xC15fE80b9d800abb72121F353a6ae6d6E9077E63",
561
+ paymentGateway: "0x0000000000000000000000000000000000000000",
562
+ a2aProtocolRegistry: "0x0000000000000000000000000000000000000000",
563
+ reputationRegistry: "0x0000000000000000000000000000000000000000",
564
+ configurationRegistry: "0x0000000000000000000000000000000000000000"
565
+ },
566
+ ipfsGateways: ["ipfs.io", "gateway.pinata.cloud", "dweb.link", "cf-ipfs.com"]
567
+ }
568
+ };
569
+
570
+ // src/react/useAgentRunner.ts
571
+ var IDENTITY_REGISTRY_ABI = [
572
+ // getAgentMetadata returns MetadataEntry[] with key+value strings
573
+ {
574
+ name: "getAgentMetadata",
575
+ type: "function",
576
+ stateMutability: "view",
577
+ inputs: [{ name: "agentId", type: "uint256" }],
578
+ outputs: [
579
+ {
580
+ name: "",
581
+ type: "tuple[]",
582
+ components: [
583
+ { name: "key", type: "string" },
584
+ { name: "value", type: "bytes" }
585
+ ]
586
+ }
587
+ ]
588
+ }
589
+ ];
590
+ var SUBSCRIPTION_MANAGER_ABI = [
591
+ {
592
+ name: "hasActiveSubscription",
593
+ type: "function",
594
+ stateMutability: "view",
595
+ inputs: [
596
+ { name: "subscriber", type: "address" },
597
+ { name: "agentId", type: "uint256" }
598
+ ],
599
+ outputs: [{ name: "", type: "bool" }]
600
+ }
601
+ ];
602
+ var ViemOnChainReader = class {
603
+ constructor(publicClient, chainConfig) {
604
+ this.publicClient = publicClient;
605
+ this.chainConfig = chainConfig;
606
+ }
607
+ publicClient;
608
+ chainConfig;
609
+ async getTokenURI(_agentId) {
610
+ return "";
611
+ }
612
+ async getAttributes(agentId) {
613
+ if (!this.publicClient) throw new Error("Public client not available");
614
+ const entries = await this.publicClient.readContract({
615
+ address: this.chainConfig.contracts.identityRegistry,
616
+ abi: IDENTITY_REGISTRY_ABI,
617
+ functionName: "getAgentMetadata",
618
+ args: [BigInt(agentId)]
619
+ });
620
+ const attrs = {};
621
+ for (const entry of entries) {
622
+ const hexStr = entry.value;
623
+ if (hexStr && hexStr !== "0x") {
624
+ attrs[entry.key] = hexToStringUTF8(hexStr);
625
+ } else {
626
+ attrs[entry.key] = "";
627
+ }
628
+ }
629
+ return attrs;
630
+ }
631
+ async hasActiveSubscription(address, agentId) {
632
+ if (!this.publicClient) return false;
633
+ try {
634
+ return await this.publicClient.readContract({
635
+ address: this.chainConfig.contracts.subscriptionManager,
636
+ abi: SUBSCRIPTION_MANAGER_ABI,
637
+ functionName: "hasActiveSubscription",
638
+ args: [address, BigInt(agentId)]
639
+ });
640
+ } catch {
641
+ return false;
642
+ }
643
+ }
644
+ };
645
+ function hexToStringUTF8(hex) {
646
+ if (!hex.startsWith("0x")) return hex;
647
+ const hexClean = hex.slice(2);
648
+ if (hexClean.length === 0) return "";
649
+ try {
650
+ const bytes = new Uint8Array(hexClean.length / 2);
651
+ for (let i = 0; i < bytes.length; i++) {
652
+ bytes[i] = parseInt(hexClean.substring(i * 2, i * 2 + 2), 16);
653
+ }
654
+ return new TextDecoder().decode(bytes);
655
+ } catch {
656
+ return hex;
657
+ }
658
+ }
659
+ function useAgentRunner(config) {
660
+ const { agentId, chainConfig: chainConfigOverride, ipfsGateways } = config;
661
+ const publicClient = (0, import_wagmi.usePublicClient)();
662
+ const { data: walletClient } = (0, import_wagmi.useWalletClient)();
663
+ const [ctx, setCtx] = (0, import_react.useState)(null);
664
+ const [isLoading, setIsLoading] = (0, import_react.useState)(false);
665
+ const [error, setError] = (0, import_react.useState)(null);
666
+ const [refetchKey, setRefetchKey] = (0, import_react.useState)(0);
667
+ const runnerRef = (0, import_react.useRef)(null);
668
+ const mountedRef = (0, import_react.useRef)(true);
669
+ (0, import_react.useEffect)(() => {
670
+ mountedRef.current = true;
671
+ return () => {
672
+ mountedRef.current = false;
673
+ };
674
+ }, []);
675
+ (0, import_react.useEffect)(() => {
676
+ if (!publicClient || !walletClient) {
677
+ setError(new Error("Wallet not connected"));
678
+ return;
679
+ }
680
+ const chainConfig = chainConfigOverride ?? (publicClient.chain?.id ? KNOWN_CHAINS[publicClient.chain.id] : void 0);
681
+ if (!chainConfig) {
682
+ setError(new Error(`Chain ${publicClient.chain?.id} not supported`));
683
+ return;
684
+ }
685
+ const reader = new ViemOnChainReader(publicClient, chainConfig);
686
+ const signer = {
687
+ async signMessage(message) {
688
+ if (!walletClient.account) throw new Error("Wallet not connected");
689
+ return walletClient.signMessage({ account: walletClient.account, message });
690
+ },
691
+ async getAddress() {
692
+ if (!walletClient.account) throw new Error("Wallet not connected");
693
+ return walletClient.account.address;
694
+ },
695
+ async getPrivateKey() {
696
+ throw new Error(
697
+ 'Private key not available via wagmi. Use window.ethereum.request({ method: "eth_private_key" }) or inject getPrivateKey via custom WalletSigner.'
698
+ );
699
+ }
700
+ };
701
+ const ipfsFetcher = new IPFSFetcher({
702
+ fallbackGateways: ipfsGateways ?? chainConfig.ipfsGateways ?? [
703
+ "gateway.pinata.cloud",
704
+ "dweb.link",
705
+ "cf-ipfs.com"
706
+ ]
707
+ });
708
+ runnerRef.current = new AgentRunner({
709
+ reader,
710
+ wallet: signer,
711
+ ipfsFetcher
712
+ });
713
+ setIsLoading(true);
714
+ setError(null);
715
+ runnerRef.current.useAgent(agentId).then((result) => {
716
+ if (mountedRef.current) {
717
+ setCtx(result);
718
+ setIsLoading(false);
719
+ }
720
+ }).catch((err) => {
721
+ if (mountedRef.current) {
722
+ setError(err instanceof Error ? err : new Error(String(err)));
723
+ setIsLoading(false);
724
+ }
725
+ });
726
+ return () => {
727
+ mountedRef.current = false;
728
+ };
729
+ }, [agentId, publicClient?.chain?.id, publicClient, walletClient, refetchKey]);
730
+ const refetch = () => setRefetchKey((k) => k + 1);
731
+ return { ctx, isLoading, error, refetch };
732
+ }
733
+ // Annotate the CommonJS export names for ESM import in node:
734
+ 0 && (module.exports = {
735
+ useAgentRunner
736
+ });
737
+ //# sourceMappingURL=index.js.map