@ens-node-metadata/agent 0.2.6 → 0.2.8

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.
@@ -0,0 +1,462 @@
1
+ // ../schemas/src/config/constants.ts
2
+ var GITHUB_URL = "https://github.com/0xLighthouse/ens-node-metadata";
3
+
4
+ // ../schemas/src/schemas/agent.ts
5
+ var AGENT_SCHEMA = {
6
+ $id: `${GITHUB_URL}/schemas/agent/1.0.0`,
7
+ source: "https://eips.ethereum.org/EIPS/eip-8004",
8
+ title: "Agent",
9
+ version: "1.0.0",
10
+ description: "AI agent identity metadata aligned with ERC-8004 registration format.",
11
+ type: "object",
12
+ properties: {
13
+ class: {
14
+ type: "string",
15
+ default: "Agent",
16
+ description: "High-level identifier of this node type"
17
+ },
18
+ "agent-uri": {
19
+ type: "string",
20
+ format: "uri",
21
+ description: "URI to the ERC-8004 registration file"
22
+ },
23
+ type: {
24
+ type: "string",
25
+ description: "Registration file type discriminator"
26
+ },
27
+ name: {
28
+ type: "string",
29
+ description: "Agent display name"
30
+ },
31
+ description: {
32
+ type: "string",
33
+ description: "Natural-language description of the agent"
34
+ },
35
+ services: {
36
+ type: "string",
37
+ description: "Advertised service endpoints"
38
+ },
39
+ "x402-support": {
40
+ type: "boolean",
41
+ description: "Whether x402 payment flow is supported"
42
+ },
43
+ active: {
44
+ type: "string",
45
+ format: "boolean",
46
+ description: "Whether the agent is currently active"
47
+ },
48
+ registrations: {
49
+ type: "string",
50
+ description: "Cross-chain identity registrations"
51
+ },
52
+ "supported-trust": {
53
+ type: "string",
54
+ description: "Trust models supported by the agent"
55
+ },
56
+ "agent-wallet": {
57
+ type: "string",
58
+ description: "Verified payout wallet for agent operations"
59
+ }
60
+ },
61
+ patternProperties: {
62
+ "^service([[^]]+])?$": {
63
+ type: "string",
64
+ description: "service[name] => endpoint, per ERC-8004 eg. service[MCP] => <ENDPOINT_URL>"
65
+ }
66
+ },
67
+ required: ["class"],
68
+ recommended: ["agent-uri"]
69
+ };
70
+
71
+ // ../schemas/src/schemas/application.ts
72
+ var APPLICATION_SCHEMA = {
73
+ $id: `${GITHUB_URL}/schemas/application/1.0.0`,
74
+ source: GITHUB_URL,
75
+ title: "Application",
76
+ version: "1.0.0",
77
+ description: "An application, service, or dApp within the organization.",
78
+ type: "object",
79
+ properties: {
80
+ class: {
81
+ type: "string",
82
+ default: "Application",
83
+ description: "High-level identifier of this node type",
84
+ examples: ["Application", "Service", "Website"]
85
+ },
86
+ name: {
87
+ type: "string",
88
+ description: "The name of the application"
89
+ },
90
+ description: {
91
+ type: "string",
92
+ description: "Description of the application's purpose and functionality"
93
+ },
94
+ url: {
95
+ type: "string",
96
+ format: "uri",
97
+ description: "URL where the application is hosted or accessed"
98
+ },
99
+ repository: {
100
+ type: "string",
101
+ description: "Source code repository URL"
102
+ },
103
+ version: {
104
+ type: "string",
105
+ description: "Current version of the application"
106
+ },
107
+ status: {
108
+ type: "string",
109
+ description: "Application status",
110
+ enum: ["Active", "Development", "Deprecated"]
111
+ }
112
+ },
113
+ required: ["class"],
114
+ recommended: ["name", "description", "url", "status"]
115
+ };
116
+
117
+ // ../schemas/src/schemas/contract.ts
118
+ var CONTRACT_SCHEMA = {
119
+ $id: `${GITHUB_URL}/schemas/contract/1.1.1`,
120
+ source: GITHUB_URL,
121
+ title: "Contract",
122
+ version: "1.1.1",
123
+ description: "Smart contract metadata profile following Enscribe smart contract metadata format.",
124
+ type: "object",
125
+ properties: {
126
+ class: {
127
+ type: "string",
128
+ default: "Contract",
129
+ description: "High-level identifier of this node type"
130
+ },
131
+ alias: {
132
+ type: "string",
133
+ description: "Human-readable contract alias (ENSIP-18 alias)"
134
+ },
135
+ description: {
136
+ type: "string",
137
+ description: "Short description of the contract purpose (ENSIP-18 description)"
138
+ },
139
+ avatar: {
140
+ type: "string",
141
+ description: "Avatar URI for the contract profile (ENSIP-12 avatar)"
142
+ },
143
+ category: {
144
+ type: "string",
145
+ description: "Contract category (e.g., defi, gaming, dao, utility, proxy, factory)"
146
+ },
147
+ license: {
148
+ type: "string",
149
+ description: "Official software license identifier for the source code"
150
+ },
151
+ docs: {
152
+ type: "string",
153
+ description: "Primary documentation URL for developers and users",
154
+ format: "uri"
155
+ },
156
+ "compiled-metadata": {
157
+ type: "string",
158
+ description: "A URI to a contract metadata file as generated by a Solidity or Vyper compiler"
159
+ },
160
+ audits: {
161
+ type: "json",
162
+ description: "JSON array of third-party audit reports"
163
+ }
164
+ },
165
+ required: ["class"],
166
+ recommended: ["alias", "description"]
167
+ };
168
+
169
+ // ../schemas/src/schemas/org.ts
170
+ var ORGANIZATION_SCHEMA = {
171
+ $id: `${GITHUB_URL}/schemas/org/0.1.5`,
172
+ source: GITHUB_URL,
173
+ title: "Organization",
174
+ version: "0.1.8",
175
+ description: "A legal or organizational entity.",
176
+ type: "object",
177
+ properties: {
178
+ class: {
179
+ type: "string",
180
+ default: "Organization",
181
+ description: "High-level identifier of this node type",
182
+ examples: ["Organization", "Foundation", "OPCo"]
183
+ },
184
+ name: {
185
+ type: "string",
186
+ description: "The name of this business unit"
187
+ },
188
+ avatar: {
189
+ type: "string",
190
+ description: "A URL to an image used as an avatar or logo"
191
+ },
192
+ description: {
193
+ type: "string",
194
+ description: "A description of the name"
195
+ },
196
+ url: {
197
+ type: "string",
198
+ format: "uri",
199
+ description: "URL of the organization"
200
+ }
201
+ },
202
+ required: ["class"],
203
+ recommended: ["name", "avatar", "description", "url"]
204
+ };
205
+
206
+ // ../schemas/src/schemas/person.ts
207
+ var PERSON_SCHEMA = {
208
+ $id: `${GITHUB_URL}/schemas/person/1.0.0`,
209
+ source: GITHUB_URL,
210
+ title: "Person",
211
+ version: "1.0.0",
212
+ description: "A person.",
213
+ type: "object",
214
+ properties: {
215
+ class: {
216
+ type: "string",
217
+ default: "Person",
218
+ description: "High-level identifier of this node type",
219
+ examples: ["Person", "Human", "Signer", "Officer", "Employee", "Secretary"]
220
+ },
221
+ "full-name": {
222
+ type: "string",
223
+ description: "Full legal or preferred name"
224
+ },
225
+ "title": {
226
+ type: "string",
227
+ description: "Title within the organization, if any"
228
+ }
229
+ }
230
+ };
231
+
232
+ // ../schemas/src/schemas/treasury.ts
233
+ var TREASURY_SCHEMA = {
234
+ $id: `${GITHUB_URL}/schemas/treasury/1.0.0`,
235
+ source: GITHUB_URL,
236
+ title: "Treasury",
237
+ version: "1.0.0",
238
+ description: "Funds and assets managed by a collective of individuals or entities.",
239
+ type: "object",
240
+ properties: {
241
+ class: {
242
+ type: "string",
243
+ default: "Treasury",
244
+ description: "High-level identifier of this node type",
245
+ examples: ["Treasury", "Vault"]
246
+ },
247
+ name: {
248
+ type: "string",
249
+ description: "The name of the treasury"
250
+ },
251
+ description: {
252
+ type: "string",
253
+ description: "A description of the name"
254
+ }
255
+ },
256
+ required: ["class"],
257
+ recommended: ["name", "description"]
258
+ };
259
+
260
+ // ../schemas/src/schemas/wallet.ts
261
+ var WALLET_SCHEMA = {
262
+ $id: `${GITHUB_URL}/schemas/wallet/1.0.0`,
263
+ source: GITHUB_URL,
264
+ title: "Wallet",
265
+ version: "1.0.0",
266
+ description: "A wallet for holding or managing assets.",
267
+ type: "object",
268
+ properties: {
269
+ class: {
270
+ type: "string",
271
+ default: "Wallet",
272
+ description: "High-level identifier of this node type",
273
+ examples: ["Wallet", "Account"]
274
+ },
275
+ description: {
276
+ type: "string",
277
+ description: "Indicates the purpose of the wallet"
278
+ }
279
+ },
280
+ required: ["class"],
281
+ recommended: ["description"]
282
+ };
283
+
284
+ // ../schemas/src/schemas/grant.ts
285
+ var GRANT_SCHEMA = {
286
+ $id: `${GITHUB_URL}/schemas/grantProgram/1.0.0`,
287
+ source: GITHUB_URL,
288
+ title: "Grant",
289
+ version: "1.0.0",
290
+ description: "A grant issued by an organization.",
291
+ type: "object",
292
+ properties: {
293
+ class: {
294
+ type: "string",
295
+ default: "Grant",
296
+ description: "High-level identifier of this node type",
297
+ examples: ["Grant", "GrantProgram"]
298
+ },
299
+ "name": {
300
+ type: "string",
301
+ description: "The name of the grant program"
302
+ },
303
+ description: {
304
+ type: "string",
305
+ description: "Description of the grant purpose and scope"
306
+ },
307
+ url: {
308
+ type: "string",
309
+ format: "uri",
310
+ description: "URL of the grant program"
311
+ },
312
+ status: {
313
+ type: "string",
314
+ description: "Grant status",
315
+ enum: ["Active", "Incomplete", "Pending", "Completed", "Cancelled"]
316
+ },
317
+ budget: {
318
+ type: "string",
319
+ description: "Total budget expressed as WEI eg. 100 USDC = 100 * 10^6"
320
+ },
321
+ token: {
322
+ type: "string",
323
+ description: 'Token expressed as ERC-20 token address eg. "0x0000000000000000000000000000000000000000"'
324
+ }
325
+ },
326
+ required: ["class"],
327
+ recommended: ["name", "description", "url", "status", "budget", "token"]
328
+ };
329
+
330
+ // ../schemas/src/schemas/delegate.ts
331
+ var DELEGATE_SCHEMA = {
332
+ $id: `${GITHUB_URL}/schemas/delegate/1.0.0`,
333
+ source: GITHUB_URL,
334
+ title: "Delegate",
335
+ version: "1.0.1",
336
+ description: "A delegate.",
337
+ type: "object",
338
+ properties: {
339
+ class: {
340
+ type: "string",
341
+ default: "Delegate",
342
+ description: "High-level identifier of this node type"
343
+ },
344
+ "address": {
345
+ type: "string",
346
+ format: "address",
347
+ description: "The address of the delegate"
348
+ },
349
+ "legal-name": {
350
+ type: "string",
351
+ description: 'The full legal or preferred name of the delegate (e.g. "John Doe")'
352
+ },
353
+ "display-name": {
354
+ type: "string",
355
+ description: "A canonical display name for the delegate"
356
+ },
357
+ statement: {
358
+ type: "string",
359
+ description: "Generic delegate statement "
360
+ },
361
+ "conflict-of-interest": {
362
+ type: "string",
363
+ description: "Generic conflict of interest declaration "
364
+ },
365
+ "forum-handle": {
366
+ type: "string",
367
+ description: 'Default forum handle (e.g. "johndoe")'
368
+ }
369
+ },
370
+ patternProperties: {
371
+ "^statement(\\[[^\\]]+\\])?$": {
372
+ type: "string",
373
+ description: "Delegate statement per organization (e.g. statement[dao.eth])"
374
+ },
375
+ "^conflict-of-interest(\\[[^\\]]+\\])?$": {
376
+ type: "string",
377
+ description: "Conflict of interest declaration per organization (e.g. conflict-of-interest[dao.eth])"
378
+ },
379
+ "^forum-handle(\\[[^\\]]+\\])?$": {
380
+ type: "string",
381
+ description: "Forum handle per organization (e.g. forum-handle[dao.eth])"
382
+ }
383
+ },
384
+ required: ["class"],
385
+ recommended: ["address", "display-name", "statement", "conflict-of-interest", "forum-handle"]
386
+ };
387
+
388
+ // ../schemas/src/schemas/group.ts
389
+ var GROUP_SCHEMA = {
390
+ $id: `${GITHUB_URL}/schemas/group/0.1.4`,
391
+ source: GITHUB_URL,
392
+ title: "Group",
393
+ version: "0.1.4",
394
+ description: "This node describes a group of individuals or entities with a shared purpose or responsibility.",
395
+ type: "object",
396
+ properties: {
397
+ class: {
398
+ type: "string",
399
+ default: "Group",
400
+ description: "High-level identifier of this node type",
401
+ examples: ["Group", "Committee", "Council", "Workgroup", "Team"]
402
+ },
403
+ name: {
404
+ type: "string",
405
+ description: "The name of the group"
406
+ },
407
+ avatar: {
408
+ type: "string",
409
+ description: "A URL to an image used as an avatar or logo"
410
+ },
411
+ description: {
412
+ type: "string",
413
+ description: "A description of the name"
414
+ },
415
+ url: {
416
+ type: "string",
417
+ format: "uri",
418
+ description: "URL of the group"
419
+ },
420
+ lead: {
421
+ type: "string",
422
+ description: "ENS name or address of the group leader"
423
+ },
424
+ "lead-title": {
425
+ type: "string",
426
+ description: "Title or role of the group leader",
427
+ examples: ["Lead Steward", "Chair", "Manager", "Owner"]
428
+ },
429
+ "members-title": {
430
+ type: "string",
431
+ description: "Title or role of the group members",
432
+ examples: ["Member", "Steward", "Contributor", "Participant"]
433
+ }
434
+ },
435
+ required: ["class"],
436
+ recommended: ["name", "lead", "avatar", "url", "description"]
437
+ };
438
+
439
+ // ../schemas/src/index.ts
440
+ var SCHEMAS = [
441
+ AGENT_SCHEMA,
442
+ APPLICATION_SCHEMA,
443
+ CONTRACT_SCHEMA,
444
+ DELEGATE_SCHEMA,
445
+ GRANT_SCHEMA,
446
+ GROUP_SCHEMA,
447
+ PERSON_SCHEMA,
448
+ ORGANIZATION_SCHEMA,
449
+ WALLET_SCHEMA,
450
+ TREASURY_SCHEMA
451
+ ];
452
+ var SCHEMA_MAP = SCHEMAS.reduce(
453
+ (map, schema) => {
454
+ map[schema.title] = schema;
455
+ return map;
456
+ },
457
+ {}
458
+ );
459
+
460
+ export {
461
+ SCHEMA_MAP
462
+ };
@@ -0,0 +1,65 @@
1
+ // src/types.ts
2
+ import { z } from "zod";
3
+ var McpServiceSchema = z.object({
4
+ name: z.literal("MCP"),
5
+ endpoint: z.string().url().describe("MCP server URL"),
6
+ version: z.string().describe("MCP protocol version date (e.g. 2025-11-25)"),
7
+ mcpTools: z.array(z.string()).optional().describe("Tool names exposed by this MCP server"),
8
+ capabilities: z.array(z.string()).optional().describe("MCP capability identifiers")
9
+ });
10
+ var A2AServiceSchema = z.object({
11
+ name: z.literal("A2A"),
12
+ endpoint: z.string().url().describe("URL to the agent card JSON (e.g. /.well-known/agent-card.json)"),
13
+ version: z.string().describe("A2A protocol version (e.g. 0.3.0)")
14
+ });
15
+ var OasfServiceSchema = z.object({
16
+ name: z.literal("OASF"),
17
+ endpoint: z.string().url().describe("OASF schema endpoint URL"),
18
+ version: z.string().describe("OASF version (e.g. 0.8.0)"),
19
+ skills: z.array(z.string()).optional().describe("Skill paths (e.g. analytical_skills/data_analysis/blockchain_analysis)"),
20
+ domains: z.array(z.string()).optional().describe("Domain paths (e.g. technology/blockchain)")
21
+ });
22
+ var AgentWalletServiceSchema = z.object({
23
+ name: z.literal("agentWallet"),
24
+ endpoint: z.string().describe("CAIP-10 wallet address (e.g. eip155:1:0x...)")
25
+ });
26
+ var WebServiceSchema = z.object({
27
+ name: z.literal("web"),
28
+ endpoint: z.string().url().describe("Human-facing web UI URL")
29
+ });
30
+ var EmailServiceSchema = z.object({
31
+ name: z.literal("email"),
32
+ endpoint: z.string().email().describe("Support email address")
33
+ });
34
+ var SCHEMA_8004_V2 = z.object({
35
+ type: z.literal("https://eips.ethereum.org/EIPS/eip-8004#registration-v1").describe("ERC-8004 registration type identifier \u2014 must be this exact URI"),
36
+ name: z.string().min(3).max(200).describe("Agent display name (3\u2013200 characters)"),
37
+ description: z.string().min(10).describe("Natural language explanation of what the agent does and its capabilities"),
38
+ image: z.string().url().optional().describe("Avatar or logo URI \u2014 PNG, SVG, WebP, or JPG; 512\xD7512px minimum recommended"),
39
+ services: z.array(z.discriminatedUnion("name", [
40
+ McpServiceSchema,
41
+ A2AServiceSchema,
42
+ OasfServiceSchema,
43
+ AgentWalletServiceSchema,
44
+ WebServiceSchema,
45
+ EmailServiceSchema
46
+ ])).describe("Communication endpoints \u2014 MCP, A2A, OASF, agentWallet, web, or email"),
47
+ registrations: z.array(z.object({
48
+ agentId: z.union([z.number().int(), z.string()]).describe("Agent token ID in the on-chain registry"),
49
+ agentRegistry: z.string().describe("CAIP-10 formatted registry contract address (e.g. eip155:1:0x...)")
50
+ })).optional().describe("On-chain NFT identity links to agent registries"),
51
+ supportedTrust: z.array(z.enum(["reputation", "crypto-economic", "tee-attestation"])).optional().describe("Trust models supported by this agent"),
52
+ active: z.boolean().default(false).describe("Whether the agent is production-ready and accepting requests (default: false)"),
53
+ x402Support: z.boolean().default(false).describe("Whether the agent supports the HTTP 402 / x402 micro-payment protocol"),
54
+ updatedAt: z.number().int().optional().describe("Unix timestamp (seconds) of the last metadata update")
55
+ });
56
+
57
+ // src/index.ts
58
+ function validateRegistrationFile(file) {
59
+ return SCHEMA_8004_V2.safeParse(file);
60
+ }
61
+
62
+ export {
63
+ SCHEMA_8004_V2,
64
+ validateRegistrationFile
65
+ };
package/dist/cli.js CHANGED
@@ -9,19 +9,19 @@ if (isRootHelp) {
9
9
  CLI for registering AI agents on ENS using ERC-8004 (v2.0).
10
10
 
11
11
  Usage:
12
- agent skill [--install]
12
+ ens-agent skill [--install]
13
13
 
14
- agent registration-file template
15
- agent registration-file validate <file.json>
16
- agent registration-file publish <file.json>
14
+ ens-agent registration-file template
15
+ ens-agent registration-file validate <file.json>
16
+ ens-agent registration-file publish <file.json>
17
17
 
18
- agent registry identity --chain-name <chain> <agent-uri>
18
+ ens-agent registry identity --chain-name <chain> <agent-uri>
19
19
 
20
- agent metadata template
21
- agent metadata validate <payload.json>
22
- agent metadata set <ens-node> <payload.json> --private-key <key> [--broadcast]
20
+ ens-agent metadata template
21
+ ens-agent metadata validate <payload.json>
22
+ ens-agent metadata set <ens-node> <payload.json> --private-key <key> [--broadcast]
23
23
 
24
- Run \`agent <command> --help\` for details on a specific command.
24
+ Run \`ens-agent <command> --help\` for details on a specific command.
25
25
  `);
26
26
  process.exit(0);
27
27
  }
@@ -0,0 +1,22 @@
1
+ import React from 'react';
2
+ import { z } from 'zod';
3
+
4
+ declare const description = "Set ENS metadata text records from a payload file";
5
+ declare const args: z.ZodTuple<[z.ZodString, z.ZodString], null>;
6
+ declare const options: z.ZodObject<{
7
+ privateKey: z.ZodString;
8
+ broadcast: z.ZodDefault<z.ZodBoolean>;
9
+ }, "strip", z.ZodTypeAny, {
10
+ privateKey: string;
11
+ broadcast: boolean;
12
+ }, {
13
+ privateKey: string;
14
+ broadcast?: boolean | undefined;
15
+ }>;
16
+ type Props = {
17
+ args: z.infer<typeof args>;
18
+ options: z.infer<typeof options>;
19
+ };
20
+ declare function Set({ args: [ensName, payloadFile], options }: Props): React.JSX.Element;
21
+
22
+ export { args, Set as default, description, options };
@@ -0,0 +1,101 @@
1
+ import {
2
+ SCHEMA_MAP
3
+ } from "../../chunk-3VTAAUSG.js";
4
+
5
+ // src/commands/metadata/set.tsx
6
+ import { readFileSync } from "fs";
7
+ import { Box, Text, useApp } from "ink";
8
+ import React from "react";
9
+ import { z } from "zod";
10
+ import { validateMetadataSchema } from "@ens-node-metadata/sdk";
11
+
12
+ // src/lib/ens-write.ts
13
+ import { http, createPublicClient, createWalletClient } from "viem";
14
+ import { privateKeyToAccount } from "viem/accounts";
15
+ import { mainnet } from "viem/chains";
16
+ async function setEnsTextRecords(ensName, texts, privateKey) {
17
+ const { addEnsContracts } = await import("@ensdomains/ensjs");
18
+ const { setRecords } = await import("@ensdomains/ensjs/wallet");
19
+ const { getResolver } = await import("@ensdomains/ensjs/public");
20
+ const account = privateKeyToAccount(privateKey);
21
+ const chain = addEnsContracts(mainnet);
22
+ const publicClient = createPublicClient({ chain, transport: http() });
23
+ const walletClient = createWalletClient({ account, chain, transport: http() });
24
+ const resolverAddress = await getResolver(publicClient, { name: ensName });
25
+ if (!resolverAddress) {
26
+ throw new Error(`No resolver found for ${ensName}. Set a resolver first.`);
27
+ }
28
+ const hash = await setRecords(walletClient, {
29
+ name: ensName,
30
+ texts,
31
+ coins: [],
32
+ resolverAddress
33
+ });
34
+ return hash;
35
+ }
36
+
37
+ // src/commands/metadata/set.tsx
38
+ var description = "Set ENS metadata text records from a payload file";
39
+ var args = z.tuple([
40
+ z.string().describe("ENS name (e.g. myagent.eth)"),
41
+ z.string().describe("payload.json")
42
+ ]);
43
+ var options = z.object({
44
+ privateKey: z.string().describe("Private key for signing (hex, prefixed with 0x)"),
45
+ broadcast: z.boolean().default(false).describe("Broadcast the transaction on-chain (default: dry run)")
46
+ });
47
+ function Set({ args: [ensName, payloadFile], options: options2 }) {
48
+ const { exit } = useApp();
49
+ const [state, setState] = React.useState({ status: "idle" });
50
+ React.useEffect(() => {
51
+ async function run() {
52
+ let payload;
53
+ try {
54
+ const raw = JSON.parse(readFileSync(payloadFile, "utf8"));
55
+ const result = validateMetadataSchema(raw, SCHEMA_MAP.Agent);
56
+ if (!result.success) {
57
+ const issues = result.errors.map((e) => `[${e.key}] ${e.message}`).join("\n");
58
+ setState({ status: "error", message: `Invalid payload:
59
+ ${issues}` });
60
+ exit(new Error("validation failed"));
61
+ return;
62
+ }
63
+ payload = result.data;
64
+ } catch (err) {
65
+ setState({ status: "error", message: `Error reading payload: ${err.message}` });
66
+ exit(new Error("read error"));
67
+ return;
68
+ }
69
+ const texts = Object.entries(payload).map(([key, value]) => ({ key, value }));
70
+ if (!options2.broadcast) {
71
+ const lines = [
72
+ `Dry run \u2014 would set ${texts.length} text records on ${ensName}:`,
73
+ "",
74
+ ...texts.map((t) => ` setText("${t.key}", "${t.value}")`),
75
+ "",
76
+ "Run with --broadcast to submit on-chain."
77
+ ];
78
+ setState({ status: "done", message: lines.join("\n") });
79
+ exit();
80
+ return;
81
+ }
82
+ setState({ status: "working", message: `Setting ${texts.length} text records on ${ensName}\u2026` });
83
+ try {
84
+ const hash = await setEnsTextRecords(ensName, texts, options2.privateKey);
85
+ setState({ status: "done", message: `\u2705 Transaction submitted: ${hash}` });
86
+ exit();
87
+ } catch (err) {
88
+ setState({ status: "error", message: `Transaction failed: ${err.message}` });
89
+ exit(new Error("tx failed"));
90
+ }
91
+ }
92
+ run();
93
+ }, [exit, ensName, payloadFile, options2]);
94
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, state.status === "idle" && /* @__PURE__ */ React.createElement(Text, { color: "gray" }, "Preparing\u2026"), state.status === "working" && /* @__PURE__ */ React.createElement(Text, { color: "cyan" }, state.message), state.status === "done" && /* @__PURE__ */ React.createElement(Text, { color: "green" }, state.message), state.status === "error" && /* @__PURE__ */ React.createElement(Text, { color: "red" }, "\u274C ", state.message));
95
+ }
96
+ export {
97
+ args,
98
+ Set as default,
99
+ description,
100
+ options
101
+ };
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+
3
+ declare const description = "Generate starter ENS metadata payload template";
4
+ declare function MetadataTemplate(): React.JSX.Element;
5
+
6
+ export { MetadataTemplate as default, description };
@@ -0,0 +1,15 @@
1
+ import {
2
+ SCHEMA_MAP
3
+ } from "../../chunk-3VTAAUSG.js";
4
+
5
+ // src/commands/metadata/template.tsx
6
+ import { Text } from "ink";
7
+ import React from "react";
8
+ var description = "Generate starter ENS metadata payload template";
9
+ function MetadataTemplate() {
10
+ return /* @__PURE__ */ React.createElement(Text, null, JSON.stringify(SCHEMA_MAP.Agent, null, 2));
11
+ }
12
+ export {
13
+ MetadataTemplate as default,
14
+ description
15
+ };
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ import { z } from 'zod';
3
+
4
+ declare const description = "Validate ENS metadata payload against agent schema";
5
+ declare const args: z.ZodTuple<[z.ZodString], null>;
6
+ type Props = {
7
+ args: z.infer<typeof args>;
8
+ };
9
+ declare function MetadataValidate({ args: [file] }: Props): React.JSX.Element;
10
+
11
+ export { args, MetadataValidate as default, description };
@@ -0,0 +1,38 @@
1
+ import {
2
+ SCHEMA_MAP
3
+ } from "../../chunk-3VTAAUSG.js";
4
+
5
+ // src/commands/metadata/validate.tsx
6
+ import { readFileSync } from "fs";
7
+ import { Box, Text, useApp } from "ink";
8
+ import React from "react";
9
+ import { z } from "zod";
10
+ import { validateMetadataSchema } from "@ens-node-metadata/sdk";
11
+ var description = "Validate ENS metadata payload against agent schema";
12
+ var args = z.tuple([z.string().describe("payload.json")]);
13
+ function MetadataValidate({ args: [file] }) {
14
+ const { exit } = useApp();
15
+ let fileError = null;
16
+ let result = null;
17
+ try {
18
+ const raw = JSON.parse(readFileSync(file, "utf8"));
19
+ result = validateMetadataSchema(raw, SCHEMA_MAP.Agent);
20
+ } catch (err) {
21
+ fileError = err.message;
22
+ }
23
+ React.useEffect(() => {
24
+ exit(fileError || result && !result.success ? new Error("validation failed") : void 0);
25
+ }, [exit, fileError, result]);
26
+ if (fileError) {
27
+ return /* @__PURE__ */ React.createElement(Text, { color: "red" }, "\u274C Error reading file: ", fileError);
28
+ }
29
+ if (result.success) {
30
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(Text, { color: "green" }, "\u2705 Valid ENS agent metadata payload"), /* @__PURE__ */ React.createElement(Text, { color: "gray" }, " ", Object.keys(result.data).length, " text records"));
31
+ }
32
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(Text, { color: "red" }, "\u274C Invalid agent metadata payload"), result.errors.map(({ key, message }) => /* @__PURE__ */ React.createElement(Text, { key, color: "red" }, " ", "[", key, "] ", message)));
33
+ }
34
+ export {
35
+ args,
36
+ MetadataValidate as default,
37
+ description
38
+ };
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ import { z } from 'zod';
3
+
4
+ declare const description = "Publish registration file to IPFS via Pinata";
5
+ declare const args: z.ZodTuple<[z.ZodString], null>;
6
+ type Props = {
7
+ args: z.infer<typeof args>;
8
+ };
9
+ declare function RegistrationFilePublish({ args: [file] }: Props): React.JSX.Element;
10
+
11
+ export { args, RegistrationFilePublish as default, description };
@@ -0,0 +1,132 @@
1
+ import {
2
+ validateRegistrationFile
3
+ } from "../../chunk-UDZL55XF.js";
4
+
5
+ // src/commands/registration-file/publish.tsx
6
+ import { readFileSync } from "fs";
7
+ import { Box, Text, useApp } from "ink";
8
+ import React from "react";
9
+ import { z } from "zod";
10
+
11
+ // ../shared/src/ipfs.ts
12
+ import fs from "fs";
13
+ import path from "path";
14
+ import { execSync } from "child_process";
15
+ function publishToIpfs(cmd, filePath) {
16
+ const output = execSync(`${cmd} ${filePath}`, { encoding: "utf8" }).trim();
17
+ const lines = output.split(/\r?\n/).filter(Boolean);
18
+ const last = lines[lines.length - 1] ?? "";
19
+ const parts = last.split(/\s+/);
20
+ if (parts.length === 1) return parts[0];
21
+ if (parts[0] === "added" && parts[1]) return parts[1];
22
+ return parts[parts.length - 1];
23
+ }
24
+ async function publishToPinata(input) {
25
+ const buffer = await fs.promises.readFile(input.filePath);
26
+ const form = new FormData();
27
+ form.set("file", new Blob([buffer]), path.basename(input.filePath));
28
+ form.set(
29
+ "pinataMetadata",
30
+ JSON.stringify({
31
+ name: `${input.schemaId}@${input.version}`,
32
+ keyvalues: { schemaId: input.schemaId, version: input.version }
33
+ })
34
+ );
35
+ const headers = {};
36
+ if (input.jwt) {
37
+ headers.Authorization = `Bearer ${input.jwt}`;
38
+ } else if (input.apiKey && input.apiSecret) {
39
+ headers.pinata_api_key = input.apiKey;
40
+ headers.pinata_secret_api_key = input.apiSecret;
41
+ }
42
+ const response = await fetch("https://api.pinata.cloud/pinning/pinFileToIPFS", {
43
+ method: "POST",
44
+ headers,
45
+ body: form
46
+ });
47
+ if (!response.ok) {
48
+ const text = await response.text();
49
+ throw new Error(`Pinata upload failed: ${response.status} ${text}`);
50
+ }
51
+ const data = await response.json();
52
+ if (!data.IpfsHash) throw new Error("Pinata response missing IpfsHash");
53
+ return data.IpfsHash;
54
+ }
55
+ async function publishFile(input) {
56
+ if (input.provider === "ipfs") {
57
+ return { cid: publishToIpfs(input.ipfsCmd ?? "ipfs add -q", input.filePath), publisher: "ipfs" };
58
+ }
59
+ const cid = await publishToPinata({
60
+ filePath: input.filePath,
61
+ jwt: input.pinataJwt,
62
+ apiKey: input.pinataKey,
63
+ apiSecret: input.pinataSecret,
64
+ schemaId: input.schemaId,
65
+ version: input.version
66
+ });
67
+ return { cid, publisher: "pinata" };
68
+ }
69
+
70
+ // src/commands/registration-file/publish.tsx
71
+ var description = "Publish registration file to IPFS via Pinata";
72
+ var args = z.tuple([z.string().describe("registration-file.json")]);
73
+ function RegistrationFilePublish({ args: [file] }) {
74
+ const { exit } = useApp();
75
+ const [state, setState] = React.useState({ status: "idle" });
76
+ React.useEffect(() => {
77
+ async function run() {
78
+ const pinataJwt = process.env.PINATA_JWT;
79
+ const pinataKey = process.env.PINATA_API_KEY;
80
+ const pinataSecret = process.env.PINATA_API_SECRET;
81
+ if (!pinataJwt && !(pinataKey && pinataSecret)) {
82
+ setState({
83
+ status: "error",
84
+ message: "Missing Pinata credentials. Set PINATA_JWT or both PINATA_API_KEY and PINATA_API_SECRET."
85
+ });
86
+ exit(new Error("missing env vars"));
87
+ return;
88
+ }
89
+ setState({ status: "validating" });
90
+ let raw;
91
+ try {
92
+ raw = JSON.parse(readFileSync(file, "utf8"));
93
+ } catch (err) {
94
+ setState({ status: "error", message: `Error reading file: ${err.message}` });
95
+ exit(new Error("read error"));
96
+ return;
97
+ }
98
+ const result = validateRegistrationFile(raw);
99
+ if (!result.success) {
100
+ const issues = result.error.issues.map((i) => `[${i.path.join(".") || "root"}] ${i.message}`).join("\n");
101
+ setState({ status: "error", message: `Invalid registration file:
102
+ ${issues}` });
103
+ exit(new Error("validation failed"));
104
+ return;
105
+ }
106
+ setState({ status: "uploading" });
107
+ try {
108
+ const { cid } = await publishFile({
109
+ provider: "pinata",
110
+ filePath: file,
111
+ pinataJwt,
112
+ pinataKey,
113
+ pinataSecret,
114
+ schemaId: result.data.name,
115
+ version: "1.0.0"
116
+ });
117
+ setState({ status: "done", uri: `ipfs://${cid}` });
118
+ exit();
119
+ } catch (err) {
120
+ setState({ status: "error", message: `Upload failed: ${err.message}` });
121
+ exit(new Error("upload failed"));
122
+ }
123
+ }
124
+ run();
125
+ }, [exit, file]);
126
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, state.status === "idle" && /* @__PURE__ */ React.createElement(Text, { color: "gray" }, "Preparing\u2026"), state.status === "validating" && /* @__PURE__ */ React.createElement(Text, { color: "cyan" }, "Validating registration file\u2026"), state.status === "uploading" && /* @__PURE__ */ React.createElement(Text, { color: "cyan" }, "Uploading to IPFS via Pinata\u2026"), state.status === "done" && /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(Text, { color: "green" }, "\u2705 Published to IPFS"), /* @__PURE__ */ React.createElement(Text, null, state.uri)), state.status === "error" && /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(Text, { color: "red" }, "\u274C ", state.message)));
127
+ }
128
+ export {
129
+ args,
130
+ RegistrationFilePublish as default,
131
+ description
132
+ };
@@ -0,0 +1,4 @@
1
+ declare const description = "Generate empty ERC-8004 v2.0 registration file template";
2
+ declare function RegistrationFileTemplate(): null;
3
+
4
+ export { RegistrationFileTemplate as default, description };
@@ -0,0 +1,51 @@
1
+ // src/commands/registration-file/template.tsx
2
+ import { useApp } from "ink";
3
+ import React from "react";
4
+ var description = "Generate empty ERC-8004 v2.0 registration file template";
5
+ var TEMPLATE = {
6
+ type: "https://eips.ethereum.org/EIPS/eip-8004#registration-v1",
7
+ name: "My Agent",
8
+ description: "A short description of what this agent does and its capabilities.",
9
+ image: "https://example.com/agent-avatar.png",
10
+ services: [
11
+ {
12
+ name: "MCP",
13
+ endpoint: "https://api.example.com/mcp",
14
+ version: "2025-11-25",
15
+ mcpTools: [],
16
+ capabilities: []
17
+ },
18
+ {
19
+ name: "A2A",
20
+ endpoint: "https://example.com/.well-known/agent-card.json",
21
+ version: "0.3.0"
22
+ },
23
+ {
24
+ name: "agentWallet",
25
+ endpoint: "eip155:1:0x0000000000000000000000000000000000000000"
26
+ }
27
+ ],
28
+ registrations: [
29
+ {
30
+ agentId: 0,
31
+ agentRegistry: "eip155:1:0x8004a6090Cd10A7288092483047B097295Fb8847"
32
+ }
33
+ ],
34
+ supportedTrust: ["reputation"],
35
+ active: false,
36
+ x402Support: false,
37
+ updatedAt: Math.floor(Date.now() / 1e3)
38
+ };
39
+ function RegistrationFileTemplate() {
40
+ const { exit } = useApp();
41
+ React.useEffect(() => {
42
+ process.stdout.write(`${JSON.stringify(TEMPLATE, null, 2)}
43
+ `);
44
+ exit();
45
+ }, [exit]);
46
+ return null;
47
+ }
48
+ export {
49
+ RegistrationFileTemplate as default,
50
+ description
51
+ };
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ import { z } from 'zod';
3
+
4
+ declare const description = "Validate registration file against ERC-8004 v2.0 schema";
5
+ declare const args: z.ZodTuple<[z.ZodString], null>;
6
+ type Props = {
7
+ args: z.infer<typeof args>;
8
+ };
9
+ declare function RegistrationFileValidate({ args: [file] }: Props): React.JSX.Element;
10
+
11
+ export { args, RegistrationFileValidate as default, description };
@@ -0,0 +1,49 @@
1
+ import {
2
+ validateRegistrationFile
3
+ } from "../../chunk-UDZL55XF.js";
4
+
5
+ // src/commands/registration-file/validate.tsx
6
+ import { readFileSync } from "fs";
7
+ import { Box as Box2, Text as Text2, useApp } from "ink";
8
+ import React2 from "react";
9
+ import { z } from "zod";
10
+
11
+ // src/lib/ui.tsx
12
+ import { Box, Text } from "ink";
13
+ import React from "react";
14
+ function ZodIssueList({ issues }) {
15
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, issues.map((issue) => {
16
+ const path = issue.path.length > 0 ? issue.path.join(".") : "(root)";
17
+ return /* @__PURE__ */ React.createElement(Box, { key: `${path}.${issue.message}` }, /* @__PURE__ */ React.createElement(Text, { color: "red" }, " ", "[", path, "] ", issue.message));
18
+ }));
19
+ }
20
+
21
+ // src/commands/registration-file/validate.tsx
22
+ var description = "Validate registration file against ERC-8004 v2.0 schema";
23
+ var args = z.tuple([z.string().describe("registration-file.json")]);
24
+ function RegistrationFileValidate({ args: [file] }) {
25
+ const { exit } = useApp();
26
+ let fileError = null;
27
+ let result = null;
28
+ try {
29
+ const raw = JSON.parse(readFileSync(file, "utf8"));
30
+ result = validateRegistrationFile(raw);
31
+ } catch (err) {
32
+ fileError = err.message;
33
+ }
34
+ React2.useEffect(() => {
35
+ exit(fileError || result && !result.success ? new Error("validation failed") : void 0);
36
+ }, [exit, fileError, result]);
37
+ if (fileError) {
38
+ return /* @__PURE__ */ React2.createElement(Text2, { color: "red" }, "\u274C Error reading file: ", fileError);
39
+ }
40
+ if (result.success) {
41
+ return /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column" }, /* @__PURE__ */ React2.createElement(Text2, { color: "green" }, "\u2705 Valid ERC-8004 v2.0 AgentRegistrationFile"));
42
+ }
43
+ return /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column" }, /* @__PURE__ */ React2.createElement(Text2, { color: "red" }, "\u274C Invalid AgentRegistrationFile"), /* @__PURE__ */ React2.createElement(ZodIssueList, { issues: result.error.issues }));
44
+ }
45
+ export {
46
+ args,
47
+ RegistrationFileValidate as default,
48
+ description
49
+ };
@@ -0,0 +1,19 @@
1
+ import React from 'react';
2
+ import { z } from 'zod';
3
+
4
+ declare const description = "Query ERC-8004 registry for agent identity";
5
+ declare const options: z.ZodObject<{
6
+ chainName: z.ZodDefault<z.ZodEnum<["base", "mainnet"]>>;
7
+ }, "strip", z.ZodTypeAny, {
8
+ chainName: "base" | "mainnet";
9
+ }, {
10
+ chainName?: "base" | "mainnet" | undefined;
11
+ }>;
12
+ declare const args: z.ZodTuple<[z.ZodString], null>;
13
+ type Props = {
14
+ options: z.infer<typeof options>;
15
+ args: z.infer<typeof args>;
16
+ };
17
+ declare function RegistryIdentity({ options: { chainName }, args: [agentUri] }: Props): React.JSX.Element;
18
+
19
+ export { args, RegistryIdentity as default, description, options };
@@ -0,0 +1,91 @@
1
+ // src/commands/registry/identity.tsx
2
+ import { Box, Text, useApp } from "ink";
3
+ import React from "react";
4
+ import { http, createPublicClient } from "viem";
5
+ import { base, mainnet } from "viem/chains";
6
+ import { z } from "zod";
7
+ var description = "Query ERC-8004 registry for agent identity";
8
+ var options = z.object({
9
+ chainName: z.enum(["base", "mainnet"]).default("mainnet").describe("Chain to query (base | mainnet)")
10
+ });
11
+ var args = z.tuple([z.string().describe("agent-uri")]);
12
+ var REGISTRY_ADDRESSES = {
13
+ mainnet: process.env.ERC8004_REGISTRY_MAINNET ?? "0x0000000000000000000000000000000000000000",
14
+ base: process.env.ERC8004_REGISTRY_BASE ?? "0x0000000000000000000000000000000000000000"
15
+ };
16
+ var ERC8004_REGISTRY_ABI = [
17
+ {
18
+ name: "agentOf",
19
+ type: "function",
20
+ stateMutability: "view",
21
+ inputs: [{ name: "agentUri", type: "string" }],
22
+ outputs: [
23
+ { name: "owner", type: "address" },
24
+ { name: "tokenId", type: "uint256" },
25
+ { name: "agentUri", type: "string" }
26
+ ]
27
+ },
28
+ {
29
+ name: "balanceOf",
30
+ type: "function",
31
+ stateMutability: "view",
32
+ inputs: [{ name: "owner", type: "address" }],
33
+ outputs: [{ name: "", type: "uint256" }]
34
+ }
35
+ ];
36
+ function RegistryIdentity({ options: { chainName }, args: [agentUri] }) {
37
+ const { exit } = useApp();
38
+ const [state, setState] = React.useState({ status: "loading" });
39
+ React.useEffect(() => {
40
+ async function run() {
41
+ const chain = chainName === "base" ? base : mainnet;
42
+ const registryAddress = REGISTRY_ADDRESSES[chainName];
43
+ if (registryAddress === "0x0000000000000000000000000000000000000000") {
44
+ setState({
45
+ status: "error",
46
+ message: `No registry address configured for ${chainName}.
47
+ Set ERC8004_REGISTRY_${chainName.toUpperCase()} env var to the contract address.`
48
+ });
49
+ exit(new Error("no registry address"));
50
+ return;
51
+ }
52
+ try {
53
+ const client = createPublicClient({
54
+ chain,
55
+ transport: http()
56
+ });
57
+ const result = await client.readContract({
58
+ address: registryAddress,
59
+ abi: ERC8004_REGISTRY_ABI,
60
+ functionName: "agentOf",
61
+ args: [agentUri]
62
+ });
63
+ setState({
64
+ status: "done",
65
+ identity: {
66
+ owner: result[0],
67
+ tokenId: result[1],
68
+ agentUri: result[2],
69
+ chain: chainName,
70
+ registryAddress
71
+ }
72
+ });
73
+ exit();
74
+ } catch (err) {
75
+ setState({
76
+ status: "error",
77
+ message: `Registry read failed: ${err.message}`
78
+ });
79
+ exit(new Error("registry read failed"));
80
+ }
81
+ }
82
+ run();
83
+ }, [exit, chainName, agentUri]);
84
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, state.status === "loading" && /* @__PURE__ */ React.createElement(Text, { color: "cyan" }, "Querying ERC-8004 registry\u2026"), state.status === "done" && /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(Text, { color: "green" }, "\u2705 Agent Identity (", state.identity.chain, ")"), /* @__PURE__ */ React.createElement(Text, null, " Agent URI: ", state.identity.agentUri), /* @__PURE__ */ React.createElement(Text, null, " Owner: ", state.identity.owner), /* @__PURE__ */ React.createElement(Text, null, " Token ID: ", state.identity.tokenId.toString()), /* @__PURE__ */ React.createElement(Text, null, " Registry: ", state.identity.registryAddress)), state.status === "error" && /* @__PURE__ */ React.createElement(Text, { color: "red" }, "\u274C ", state.message));
85
+ }
86
+ export {
87
+ args,
88
+ RegistryIdentity as default,
89
+ description,
90
+ options
91
+ };
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ import { z } from 'zod';
3
+
4
+ declare const description = "Print or install SKILL.md guide";
5
+ declare const options: z.ZodObject<{
6
+ install: z.ZodDefault<z.ZodBoolean>;
7
+ }, "strip", z.ZodTypeAny, {
8
+ install: boolean;
9
+ }, {
10
+ install?: boolean | undefined;
11
+ }>;
12
+ type Props = {
13
+ options: z.infer<typeof options>;
14
+ };
15
+ declare function Skill({ options: { install } }: Props): React.JSX.Element;
16
+
17
+ export { Skill as default, description, options };
@@ -0,0 +1,53 @@
1
+ // src/commands/skill.tsx
2
+ import { copyFileSync, existsSync, readFileSync } from "fs";
3
+ import { dirname, join, resolve } from "path";
4
+ import { fileURLToPath } from "url";
5
+ import { Text, useApp } from "ink";
6
+ import React from "react";
7
+ import { z } from "zod";
8
+ var description = "Print or install SKILL.md guide";
9
+ var options = z.object({
10
+ install: z.boolean().default(false).describe("Copy SKILL.md to the current working directory")
11
+ });
12
+ var __dirname = dirname(fileURLToPath(import.meta.url));
13
+ function getSkillMdPath() {
14
+ const candidates = [
15
+ join(__dirname, "../../SKILL.md"),
16
+ join(__dirname, "../SKILL.md"),
17
+ join(__dirname, "SKILL.md")
18
+ ];
19
+ for (const p of candidates) {
20
+ if (existsSync(p)) return p;
21
+ }
22
+ throw new Error("SKILL.md not found in package");
23
+ }
24
+ function Skill({ options: { install } }) {
25
+ const { exit } = useApp();
26
+ const [output, setOutput] = React.useState("");
27
+ const [error, setError] = React.useState(null);
28
+ React.useEffect(() => {
29
+ try {
30
+ const skillPath = getSkillMdPath();
31
+ const content = readFileSync(skillPath, "utf8");
32
+ if (install) {
33
+ const dest = resolve(process.cwd(), "SKILL.md");
34
+ copyFileSync(skillPath, dest);
35
+ setOutput(`\u2705 SKILL.md copied to ${dest}`);
36
+ } else {
37
+ setOutput(content);
38
+ }
39
+ } catch (err) {
40
+ setError(err.message);
41
+ }
42
+ exit();
43
+ }, [exit, install]);
44
+ if (error) {
45
+ return /* @__PURE__ */ React.createElement(Text, { color: "red" }, "\u274C ", error);
46
+ }
47
+ return /* @__PURE__ */ React.createElement(Text, null, output);
48
+ }
49
+ export {
50
+ Skill as default,
51
+ description,
52
+ options
53
+ };
package/dist/index.js CHANGED
@@ -1,63 +1,7 @@
1
- // src/types.ts
2
- import { z } from "zod";
3
- var McpServiceSchema = z.object({
4
- name: z.literal("MCP"),
5
- endpoint: z.string().url().describe("MCP server URL"),
6
- version: z.string().describe("MCP protocol version date (e.g. 2025-11-25)"),
7
- mcpTools: z.array(z.string()).optional().describe("Tool names exposed by this MCP server"),
8
- capabilities: z.array(z.string()).optional().describe("MCP capability identifiers")
9
- });
10
- var A2AServiceSchema = z.object({
11
- name: z.literal("A2A"),
12
- endpoint: z.string().url().describe("URL to the agent card JSON (e.g. /.well-known/agent-card.json)"),
13
- version: z.string().describe("A2A protocol version (e.g. 0.3.0)")
14
- });
15
- var OasfServiceSchema = z.object({
16
- name: z.literal("OASF"),
17
- endpoint: z.string().url().describe("OASF schema endpoint URL"),
18
- version: z.string().describe("OASF version (e.g. 0.8.0)"),
19
- skills: z.array(z.string()).optional().describe("Skill paths (e.g. analytical_skills/data_analysis/blockchain_analysis)"),
20
- domains: z.array(z.string()).optional().describe("Domain paths (e.g. technology/blockchain)")
21
- });
22
- var AgentWalletServiceSchema = z.object({
23
- name: z.literal("agentWallet"),
24
- endpoint: z.string().describe("CAIP-10 wallet address (e.g. eip155:1:0x...)")
25
- });
26
- var WebServiceSchema = z.object({
27
- name: z.literal("web"),
28
- endpoint: z.string().url().describe("Human-facing web UI URL")
29
- });
30
- var EmailServiceSchema = z.object({
31
- name: z.literal("email"),
32
- endpoint: z.string().email().describe("Support email address")
33
- });
34
- var SCHEMA_8004_V2 = z.object({
35
- type: z.literal("https://eips.ethereum.org/EIPS/eip-8004#registration-v1").describe("ERC-8004 registration type identifier \u2014 must be this exact URI"),
36
- name: z.string().min(3).max(200).describe("Agent display name (3\u2013200 characters)"),
37
- description: z.string().min(10).describe("Natural language explanation of what the agent does and its capabilities"),
38
- image: z.string().url().optional().describe("Avatar or logo URI \u2014 PNG, SVG, WebP, or JPG; 512\xD7512px minimum recommended"),
39
- services: z.array(z.discriminatedUnion("name", [
40
- McpServiceSchema,
41
- A2AServiceSchema,
42
- OasfServiceSchema,
43
- AgentWalletServiceSchema,
44
- WebServiceSchema,
45
- EmailServiceSchema
46
- ])).describe("Communication endpoints \u2014 MCP, A2A, OASF, agentWallet, web, or email"),
47
- registrations: z.array(z.object({
48
- agentId: z.union([z.number().int(), z.string()]).describe("Agent token ID in the on-chain registry"),
49
- agentRegistry: z.string().describe("CAIP-10 formatted registry contract address (e.g. eip155:1:0x...)")
50
- })).optional().describe("On-chain NFT identity links to agent registries"),
51
- supportedTrust: z.array(z.enum(["reputation", "crypto-economic", "tee-attestation"])).optional().describe("Trust models supported by this agent"),
52
- active: z.boolean().default(false).describe("Whether the agent is production-ready and accepting requests (default: false)"),
53
- x402Support: z.boolean().default(false).describe("Whether the agent supports the HTTP 402 / x402 micro-payment protocol"),
54
- updatedAt: z.number().int().optional().describe("Unix timestamp (seconds) of the last metadata update")
55
- });
56
-
57
- // src/index.ts
58
- function validateRegistrationFile(file) {
59
- return SCHEMA_8004_V2.safeParse(file);
60
- }
1
+ import {
2
+ SCHEMA_8004_V2,
3
+ validateRegistrationFile
4
+ } from "./chunk-UDZL55XF.js";
61
5
  export {
62
6
  SCHEMA_8004_V2,
63
7
  validateRegistrationFile
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ens-node-metadata/agent",
3
- "version": "0.2.6",
3
+ "version": "0.2.8",
4
4
  "description": "CLI for registering AI agents on ENS using ERC-8004",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",