@ens-node-metadata/agent 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -110
- package/dist/cli.d.ts +0 -2
- package/dist/cli.js +9 -7
- package/dist/index.d.ts +188 -5
- package/dist/index.js +63 -4
- package/package.json +8 -4
- package/dist/cli.d.ts.map +0 -1
- package/dist/commands/metadata/set.d.ts +0 -21
- package/dist/commands/metadata/set.d.ts.map +0 -1
- package/dist/commands/metadata/set.js +0 -75
- package/dist/commands/metadata/template.d.ts +0 -4
- package/dist/commands/metadata/template.d.ts.map +0 -1
- package/dist/commands/metadata/template.js +0 -7
- package/dist/commands/metadata/validate.d.ts +0 -10
- package/dist/commands/metadata/validate.d.ts.map +0 -1
- package/dist/commands/metadata/validate.js +0 -44
- package/dist/commands/register.d.ts +0 -21
- package/dist/commands/register.d.ts.map +0 -1
- package/dist/commands/register.js +0 -76
- package/dist/commands/registration-file/publish.d.ts +0 -10
- package/dist/commands/registration-file/publish.d.ts.map +0 -1
- package/dist/commands/registration-file/publish.js +0 -79
- package/dist/commands/registration-file/template.d.ts +0 -3
- package/dist/commands/registration-file/template.d.ts.map +0 -1
- package/dist/commands/registration-file/template.js +0 -48
- package/dist/commands/registration-file/validate.d.ts +0 -10
- package/dist/commands/registration-file/validate.d.ts.map +0 -1
- package/dist/commands/registration-file/validate.js +0 -35
- package/dist/commands/registry/identity.d.ts +0 -18
- package/dist/commands/registry/identity.d.ts.map +0 -1
- package/dist/commands/registry/identity.js +0 -115
- package/dist/commands/skill.d.ts +0 -16
- package/dist/commands/skill.d.ts.map +0 -1
- package/dist/commands/skill.js +0 -53
- package/dist/commands/update.d.ts +0 -21
- package/dist/commands/update.d.ts.map +0 -1
- package/dist/commands/update.js +0 -76
- package/dist/index.d.ts.map +0 -1
- package/dist/lib/ens-write.d.ts +0 -6
- package/dist/lib/ens-write.d.ts.map +0 -1
- package/dist/lib/ens-write.js +0 -23
- package/dist/lib/ui.d.ts +0 -6
- package/dist/lib/ui.d.ts.map +0 -1
- package/dist/lib/ui.js +0 -14
- package/dist/types.d.ts +0 -181
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -84
- package/src/index.ts +0 -8
package/README.md
CHANGED
|
@@ -8,119 +8,11 @@ CLI for registering AI agents on ENS using [ERC-8004](https://best-practices.800
|
|
|
8
8
|
pnpm dlx @ens-node-metadata/agent --help
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
## Commands
|
|
12
|
-
|
|
13
|
-
```sh
|
|
14
|
-
agent skill [--install]
|
|
15
|
-
Print SKILL.md. With --install, copy it to the current directory.
|
|
16
|
-
|
|
17
|
-
agent registration-file template
|
|
18
|
-
Print an empty ERC-8004 v2.0 registration JSON to stdout.
|
|
19
|
-
|
|
20
|
-
agent registration-file validate <registration-file.json>
|
|
21
|
-
Validate against Zod schema. Prints ✅ or errors ❌.
|
|
22
|
-
Emits WA031 deprecation warning if the legacy `endpoints` field is used.
|
|
23
|
-
|
|
24
|
-
agent registration-file publish <registration-file.json>
|
|
25
|
-
Publish to IPFS via @web3-storage/w3up-client. Prints the ipfs:// URI.
|
|
26
|
-
Requires: W3_PRINCIPAL, W3_PROOF env vars (see below).
|
|
27
|
-
|
|
28
|
-
agent registry identity --chain-name <chain> <agent-uri>
|
|
29
|
-
Read the ERC-8004 Identity Registry for the given chain.
|
|
30
|
-
Supported chains: base, mainnet.
|
|
31
|
-
Requires: ERC8004_REGISTRY_<CHAIN> env var.
|
|
32
|
-
|
|
33
|
-
agent metadata template
|
|
34
|
-
Print a starter ENS metadata payload JSON (the text records to set).
|
|
35
|
-
|
|
36
|
-
agent metadata validate <payload.json>
|
|
37
|
-
Validate ENS metadata payload against the agent schema.
|
|
38
|
-
|
|
39
|
-
agent register <ENS> <payload.json> --private-key <key> [--broadcast]
|
|
40
|
-
Build ENS setTextRecords transaction. Dry run by default; --broadcast submits it.
|
|
41
|
-
Uses viem + @ensdomains/ensjs.
|
|
42
|
-
|
|
43
|
-
agent update <ENS> <payload.json> --private-key <key> [--broadcast]
|
|
44
|
-
Same as register — for updating existing records.
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
## Environment Variables
|
|
48
|
-
|
|
49
|
-
Optional
|
|
50
|
-
|
|
51
|
-
* PINATA_API_KEY
|
|
52
|
-
* PINATA_API_SECRET
|
|
53
|
-
* PINATA_JWT
|
|
54
|
-
|
|
55
|
-
## ERC-8004 v2.0 Registration File
|
|
56
|
-
|
|
57
|
-
The registration file is a JSON document published to IPFS or HTTPS. Its `ipfs://` URI is stored as the `agent-uri` ENS text record.
|
|
58
|
-
|
|
59
|
-
```json
|
|
60
|
-
{
|
|
61
|
-
"type": "Agent",
|
|
62
|
-
"name": "My Agent",
|
|
63
|
-
"description": "Does useful things on-chain.",
|
|
64
|
-
"services": [
|
|
65
|
-
{ "name": "MCP", "endpoint": "https://myagent.example.com/mcp", "version": "1.0" },
|
|
66
|
-
{ "name": "A2A", "endpoint": "https://myagent.example.com/a2a", "version": "0.3" }
|
|
67
|
-
],
|
|
68
|
-
"x402Support": false,
|
|
69
|
-
"active": true,
|
|
70
|
-
"registrations": [],
|
|
71
|
-
"supportedTrust": ["reputation"]
|
|
72
|
-
}
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
> ⚠️ **v2.0 migration:** The field name changed from `endpoints` → `services` (Jan 2026).
|
|
76
|
-
> The CLI accepts `endpoints` for backward compatibility with a WA031 deprecation warning.
|
|
77
|
-
|
|
78
11
|
## Registration Flow
|
|
79
12
|
|
|
80
|
-
1. `agent registration-file template > registration.json` — create the file
|
|
81
|
-
2. Edit `registration.json`
|
|
82
|
-
3. `agent registration-file validate registration.json` — validate
|
|
83
|
-
4. `agent registration-file publish registration.json` — publish to IPFS → get `ipfs://` URI
|
|
84
|
-
5. `agent metadata template > payload.json` — create the ENS record payload
|
|
85
|
-
6. Set `agent-uri` to the `ipfs://` URI in `payload.json`
|
|
86
|
-
7. `agent metadata validate payload.json` — validate
|
|
87
|
-
8. `agent register myagent.eth payload.json --private-key $PK --broadcast` — register
|
|
88
|
-
|
|
89
13
|
See [SKILL.md](./SKILL.md) for the full step-by-step guide.
|
|
90
14
|
|
|
91
|
-
## TypeScript API
|
|
92
|
-
|
|
93
|
-
```ts
|
|
94
|
-
import {
|
|
95
|
-
buildRegistrationFile,
|
|
96
|
-
validateRegistrationFile,
|
|
97
|
-
AgentRegistrationFileSchema,
|
|
98
|
-
} from "@ens-node-metadata/agent";
|
|
99
|
-
|
|
100
|
-
// Build a registration file
|
|
101
|
-
const file = buildRegistrationFile({
|
|
102
|
-
name: "My AI Agent",
|
|
103
|
-
description: "Does useful things on-chain.",
|
|
104
|
-
services: [
|
|
105
|
-
{ name: "MCP", endpoint: "https://myagent.example.com/mcp", version: "1.0" },
|
|
106
|
-
],
|
|
107
|
-
active: true,
|
|
108
|
-
supportedTrust: ["reputation"],
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
// Validate an untrusted payload
|
|
112
|
-
const raw = JSON.parse(maybeInvalidJson);
|
|
113
|
-
const result = validateRegistrationFile(raw);
|
|
114
|
-
if (result.success) {
|
|
115
|
-
console.log(result.data.name);
|
|
116
|
-
// Check for legacy `endpoints` field usage
|
|
117
|
-
if (result.data._legacyEndpoints) {
|
|
118
|
-
console.warn("WA031: migrate from `endpoints` to `services`");
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
```
|
|
122
|
-
|
|
123
15
|
## Related Packages
|
|
124
16
|
|
|
125
|
-
* [`@ens-node-metadata/schemas`](
|
|
126
|
-
* [`@ens-node-metadata/sdk`](
|
|
17
|
+
* [`@ens-node-metadata/schemas`](#TODO) — JSON schemas for all ENS node types
|
|
18
|
+
* [`@ens-node-metadata/sdk`](https://www.npmjs.com/package/@ens-node-metadata/sdk) — ENS metadata read SDK
|
package/dist/cli.d.ts
CHANGED
package/dist/cli.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
|
|
3
|
+
// src/cli.ts
|
|
4
|
+
import Pastel from "pastel";
|
|
5
|
+
var args = process.argv.slice(2);
|
|
6
|
+
var isRootHelp = args.length === 0 || args.length === 1 && (args[0] === "--help" || args[0] === "-h");
|
|
5
7
|
if (isRootHelp) {
|
|
6
|
-
|
|
8
|
+
console.log(`
|
|
7
9
|
CLI for registering AI agents on ENS using ERC-8004 (v2.0).
|
|
8
10
|
|
|
9
11
|
Usage:
|
|
@@ -21,9 +23,9 @@ Usage:
|
|
|
21
23
|
|
|
22
24
|
Run \`agent <command> --help\` for details on a specific command.
|
|
23
25
|
`);
|
|
24
|
-
|
|
26
|
+
process.exit(0);
|
|
25
27
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
+
var app = new Pastel({
|
|
29
|
+
importMeta: import.meta
|
|
28
30
|
});
|
|
29
31
|
await app.run();
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,190 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import * as zod from 'zod';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Zod schema for ERC-8004 v2.0 agent registration files.
|
|
6
|
+
* @see https://best-practices.8004scan.io/docs/01-agent-metadata-standard.html
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
declare const SCHEMA_8004_V2: z.ZodObject<{
|
|
10
|
+
type: z.ZodLiteral<"https://eips.ethereum.org/EIPS/eip-8004#registration-v1">;
|
|
11
|
+
name: z.ZodString;
|
|
12
|
+
description: z.ZodString;
|
|
13
|
+
image: z.ZodOptional<z.ZodString>;
|
|
14
|
+
services: z.ZodArray<z.ZodDiscriminatedUnion<"name", [z.ZodObject<{
|
|
15
|
+
name: z.ZodLiteral<"MCP">;
|
|
16
|
+
endpoint: z.ZodString;
|
|
17
|
+
version: z.ZodString;
|
|
18
|
+
mcpTools: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
19
|
+
capabilities: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
20
|
+
}, "strip", z.ZodTypeAny, {
|
|
21
|
+
name: "MCP";
|
|
22
|
+
endpoint: string;
|
|
23
|
+
version: string;
|
|
24
|
+
mcpTools?: string[] | undefined;
|
|
25
|
+
capabilities?: string[] | undefined;
|
|
26
|
+
}, {
|
|
27
|
+
name: "MCP";
|
|
28
|
+
endpoint: string;
|
|
29
|
+
version: string;
|
|
30
|
+
mcpTools?: string[] | undefined;
|
|
31
|
+
capabilities?: string[] | undefined;
|
|
32
|
+
}>, z.ZodObject<{
|
|
33
|
+
name: z.ZodLiteral<"A2A">;
|
|
34
|
+
endpoint: z.ZodString;
|
|
35
|
+
version: z.ZodString;
|
|
36
|
+
}, "strip", z.ZodTypeAny, {
|
|
37
|
+
name: "A2A";
|
|
38
|
+
endpoint: string;
|
|
39
|
+
version: string;
|
|
40
|
+
}, {
|
|
41
|
+
name: "A2A";
|
|
42
|
+
endpoint: string;
|
|
43
|
+
version: string;
|
|
44
|
+
}>, z.ZodObject<{
|
|
45
|
+
name: z.ZodLiteral<"OASF">;
|
|
46
|
+
endpoint: z.ZodString;
|
|
47
|
+
version: z.ZodString;
|
|
48
|
+
skills: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
49
|
+
domains: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
50
|
+
}, "strip", z.ZodTypeAny, {
|
|
51
|
+
name: "OASF";
|
|
52
|
+
endpoint: string;
|
|
53
|
+
version: string;
|
|
54
|
+
skills?: string[] | undefined;
|
|
55
|
+
domains?: string[] | undefined;
|
|
56
|
+
}, {
|
|
57
|
+
name: "OASF";
|
|
58
|
+
endpoint: string;
|
|
59
|
+
version: string;
|
|
60
|
+
skills?: string[] | undefined;
|
|
61
|
+
domains?: string[] | undefined;
|
|
62
|
+
}>, z.ZodObject<{
|
|
63
|
+
name: z.ZodLiteral<"agentWallet">;
|
|
64
|
+
endpoint: z.ZodString;
|
|
65
|
+
}, "strip", z.ZodTypeAny, {
|
|
66
|
+
name: "agentWallet";
|
|
67
|
+
endpoint: string;
|
|
68
|
+
}, {
|
|
69
|
+
name: "agentWallet";
|
|
70
|
+
endpoint: string;
|
|
71
|
+
}>, z.ZodObject<{
|
|
72
|
+
name: z.ZodLiteral<"web">;
|
|
73
|
+
endpoint: z.ZodString;
|
|
74
|
+
}, "strip", z.ZodTypeAny, {
|
|
75
|
+
name: "web";
|
|
76
|
+
endpoint: string;
|
|
77
|
+
}, {
|
|
78
|
+
name: "web";
|
|
79
|
+
endpoint: string;
|
|
80
|
+
}>, z.ZodObject<{
|
|
81
|
+
name: z.ZodLiteral<"email">;
|
|
82
|
+
endpoint: z.ZodString;
|
|
83
|
+
}, "strip", z.ZodTypeAny, {
|
|
84
|
+
name: "email";
|
|
85
|
+
endpoint: string;
|
|
86
|
+
}, {
|
|
87
|
+
name: "email";
|
|
88
|
+
endpoint: string;
|
|
89
|
+
}>]>, "many">;
|
|
90
|
+
registrations: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
91
|
+
agentId: z.ZodUnion<[z.ZodNumber, z.ZodString]>;
|
|
92
|
+
agentRegistry: z.ZodString;
|
|
93
|
+
}, "strip", z.ZodTypeAny, {
|
|
94
|
+
agentId: string | number;
|
|
95
|
+
agentRegistry: string;
|
|
96
|
+
}, {
|
|
97
|
+
agentId: string | number;
|
|
98
|
+
agentRegistry: string;
|
|
99
|
+
}>, "many">>;
|
|
100
|
+
supportedTrust: z.ZodOptional<z.ZodArray<z.ZodEnum<["reputation", "crypto-economic", "tee-attestation"]>, "many">>;
|
|
101
|
+
active: z.ZodDefault<z.ZodBoolean>;
|
|
102
|
+
x402Support: z.ZodDefault<z.ZodBoolean>;
|
|
103
|
+
updatedAt: z.ZodOptional<z.ZodNumber>;
|
|
104
|
+
}, "strip", z.ZodTypeAny, {
|
|
105
|
+
type: "https://eips.ethereum.org/EIPS/eip-8004#registration-v1";
|
|
106
|
+
name: string;
|
|
107
|
+
description: string;
|
|
108
|
+
services: ({
|
|
109
|
+
name: "MCP";
|
|
110
|
+
endpoint: string;
|
|
111
|
+
version: string;
|
|
112
|
+
mcpTools?: string[] | undefined;
|
|
113
|
+
capabilities?: string[] | undefined;
|
|
114
|
+
} | {
|
|
115
|
+
name: "A2A";
|
|
116
|
+
endpoint: string;
|
|
117
|
+
version: string;
|
|
118
|
+
} | {
|
|
119
|
+
name: "OASF";
|
|
120
|
+
endpoint: string;
|
|
121
|
+
version: string;
|
|
122
|
+
skills?: string[] | undefined;
|
|
123
|
+
domains?: string[] | undefined;
|
|
124
|
+
} | {
|
|
125
|
+
name: "agentWallet";
|
|
126
|
+
endpoint: string;
|
|
127
|
+
} | {
|
|
128
|
+
name: "web";
|
|
129
|
+
endpoint: string;
|
|
130
|
+
} | {
|
|
131
|
+
name: "email";
|
|
132
|
+
endpoint: string;
|
|
133
|
+
})[];
|
|
134
|
+
active: boolean;
|
|
135
|
+
x402Support: boolean;
|
|
136
|
+
image?: string | undefined;
|
|
137
|
+
registrations?: {
|
|
138
|
+
agentId: string | number;
|
|
139
|
+
agentRegistry: string;
|
|
140
|
+
}[] | undefined;
|
|
141
|
+
supportedTrust?: ("reputation" | "crypto-economic" | "tee-attestation")[] | undefined;
|
|
142
|
+
updatedAt?: number | undefined;
|
|
143
|
+
}, {
|
|
144
|
+
type: "https://eips.ethereum.org/EIPS/eip-8004#registration-v1";
|
|
4
145
|
name: string;
|
|
146
|
+
description: string;
|
|
147
|
+
services: ({
|
|
148
|
+
name: "MCP";
|
|
149
|
+
endpoint: string;
|
|
150
|
+
version: string;
|
|
151
|
+
mcpTools?: string[] | undefined;
|
|
152
|
+
capabilities?: string[] | undefined;
|
|
153
|
+
} | {
|
|
154
|
+
name: "A2A";
|
|
155
|
+
endpoint: string;
|
|
156
|
+
version: string;
|
|
157
|
+
} | {
|
|
158
|
+
name: "OASF";
|
|
159
|
+
endpoint: string;
|
|
160
|
+
version: string;
|
|
161
|
+
skills?: string[] | undefined;
|
|
162
|
+
domains?: string[] | undefined;
|
|
163
|
+
} | {
|
|
164
|
+
name: "agentWallet";
|
|
165
|
+
endpoint: string;
|
|
166
|
+
} | {
|
|
167
|
+
name: "web";
|
|
168
|
+
endpoint: string;
|
|
169
|
+
} | {
|
|
170
|
+
name: "email";
|
|
171
|
+
endpoint: string;
|
|
172
|
+
})[];
|
|
173
|
+
image?: string | undefined;
|
|
174
|
+
registrations?: {
|
|
175
|
+
agentId: string | number;
|
|
176
|
+
agentRegistry: string;
|
|
177
|
+
}[] | undefined;
|
|
178
|
+
supportedTrust?: ("reputation" | "crypto-economic" | "tee-attestation")[] | undefined;
|
|
179
|
+
active?: boolean | undefined;
|
|
180
|
+
x402Support?: boolean | undefined;
|
|
181
|
+
updatedAt?: number | undefined;
|
|
182
|
+
}>;
|
|
183
|
+
type AgentRegistrationFile = z.infer<typeof SCHEMA_8004_V2>;
|
|
184
|
+
|
|
185
|
+
declare function validateRegistrationFile(file: unknown): zod.SafeParseReturnType<{
|
|
5
186
|
type: "https://eips.ethereum.org/EIPS/eip-8004#registration-v1";
|
|
187
|
+
name: string;
|
|
6
188
|
description: string;
|
|
7
189
|
services: ({
|
|
8
190
|
name: "MCP";
|
|
@@ -40,8 +222,8 @@ export declare function validateRegistrationFile(file: unknown): import("zod").S
|
|
|
40
222
|
x402Support?: boolean | undefined;
|
|
41
223
|
updatedAt?: number | undefined;
|
|
42
224
|
}, {
|
|
43
|
-
name: string;
|
|
44
225
|
type: "https://eips.ethereum.org/EIPS/eip-8004#registration-v1";
|
|
226
|
+
name: string;
|
|
45
227
|
description: string;
|
|
46
228
|
services: ({
|
|
47
229
|
name: "MCP";
|
|
@@ -79,4 +261,5 @@ export declare function validateRegistrationFile(file: unknown): import("zod").S
|
|
|
79
261
|
supportedTrust?: ("reputation" | "crypto-economic" | "tee-attestation")[] | undefined;
|
|
80
262
|
updatedAt?: number | undefined;
|
|
81
263
|
}>;
|
|
82
|
-
|
|
264
|
+
|
|
265
|
+
export { type AgentRegistrationFile, SCHEMA_8004_V2, validateRegistrationFile };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,64 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
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);
|
|
5
60
|
}
|
|
61
|
+
export {
|
|
62
|
+
SCHEMA_8004_V2,
|
|
63
|
+
validateRegistrationFile
|
|
64
|
+
};
|
package/package.json
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ens-node-metadata/agent",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "CLI for registering AI agents on ENS using ERC-8004",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"main": "./
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
7
8
|
"bin": {
|
|
8
9
|
"agent": "./dist/cli.js"
|
|
9
10
|
},
|
|
10
11
|
"exports": {
|
|
11
|
-
".": "./
|
|
12
|
+
".": "./dist/index.js"
|
|
12
13
|
},
|
|
13
14
|
"files": [
|
|
14
15
|
"dist",
|
|
@@ -33,12 +34,15 @@
|
|
|
33
34
|
"devDependencies": {
|
|
34
35
|
"@types/node": "^25.3.0",
|
|
35
36
|
"@types/react": "^19.2.14",
|
|
37
|
+
"tsup": "^8.5.1",
|
|
36
38
|
"typescript": "^5",
|
|
37
39
|
"tsconfig": "0.0.0"
|
|
38
40
|
},
|
|
39
41
|
"scripts": {
|
|
42
|
+
"version:patch": "pnpm version patch --no-git-tag-version",
|
|
43
|
+
"version:minor": "pnpm version minor --no-git-tag-version",
|
|
40
44
|
"agent": "bun src/cli.ts",
|
|
41
|
-
"build": "
|
|
45
|
+
"build": "tsup",
|
|
42
46
|
"lint": "biome check ."
|
|
43
47
|
}
|
|
44
48
|
}
|
package/dist/cli.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { z } from 'zod';
|
|
3
|
-
export declare const description = "Set ENS metadata text records from a payload file";
|
|
4
|
-
export declare const args: z.ZodTuple<[z.ZodString, z.ZodString], null>;
|
|
5
|
-
export declare const options: z.ZodObject<{
|
|
6
|
-
privateKey: z.ZodString;
|
|
7
|
-
broadcast: z.ZodDefault<z.ZodBoolean>;
|
|
8
|
-
}, "strip", z.ZodTypeAny, {
|
|
9
|
-
privateKey: string;
|
|
10
|
-
broadcast: boolean;
|
|
11
|
-
}, {
|
|
12
|
-
privateKey: string;
|
|
13
|
-
broadcast?: boolean | undefined;
|
|
14
|
-
}>;
|
|
15
|
-
type Props = {
|
|
16
|
-
args: z.infer<typeof args>;
|
|
17
|
-
options: z.infer<typeof options>;
|
|
18
|
-
};
|
|
19
|
-
export default function Set({ args: [ensName, payloadFile], options }: Props): React.JSX.Element;
|
|
20
|
-
export {};
|
|
21
|
-
//# sourceMappingURL=set.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"set.d.ts","sourceRoot":"","sources":["../../../src/commands/metadata/set.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAKvB,eAAO,MAAM,WAAW,sDAAsD,CAAA;AAE9E,eAAO,MAAM,IAAI,8CAGf,CAAA;AAEF,eAAO,MAAM,OAAO;;;;;;;;;EAMlB,CAAA;AAEF,KAAK,KAAK,GAAG;IACX,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,CAAA;IAC1B,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,OAAO,CAAC,CAAA;CACjC,CAAA;AAQD,MAAM,CAAC,OAAO,UAAU,GAAG,CAAC,EAAE,IAAI,EAAE,CAAC,OAAO,EAAE,WAAW,CAAC,EAAE,OAAO,EAAE,EAAE,KAAK,qBA4D3E"}
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import { readFileSync } from 'node:fs';
|
|
2
|
-
import { Box, Text, useApp } from 'ink';
|
|
3
|
-
import React from 'react';
|
|
4
|
-
import { z } from 'zod';
|
|
5
|
-
import { SCHEMA_MAP } from '@ens-node-metadata/schemas';
|
|
6
|
-
import { validateMetadataSchema } from '@ens-node-metadata/sdk';
|
|
7
|
-
import { setEnsTextRecords } from '../../lib/ens-write.js';
|
|
8
|
-
export const description = 'Set ENS metadata text records from a payload file';
|
|
9
|
-
export const args = z.tuple([
|
|
10
|
-
z.string().describe('ENS name (e.g. myagent.eth)'),
|
|
11
|
-
z.string().describe('payload.json'),
|
|
12
|
-
]);
|
|
13
|
-
export const options = z.object({
|
|
14
|
-
privateKey: z.string().describe('Private key for signing (hex, prefixed with 0x)'),
|
|
15
|
-
broadcast: z
|
|
16
|
-
.boolean()
|
|
17
|
-
.default(false)
|
|
18
|
-
.describe('Broadcast the transaction on-chain (default: dry run)'),
|
|
19
|
-
});
|
|
20
|
-
export default function Set({ args: [ensName, payloadFile], options }) {
|
|
21
|
-
const { exit } = useApp();
|
|
22
|
-
const [state, setState] = React.useState({ status: 'idle' });
|
|
23
|
-
React.useEffect(() => {
|
|
24
|
-
async function run() {
|
|
25
|
-
let payload;
|
|
26
|
-
try {
|
|
27
|
-
const raw = JSON.parse(readFileSync(payloadFile, 'utf8'));
|
|
28
|
-
const result = validateMetadataSchema(raw, SCHEMA_MAP.Agent);
|
|
29
|
-
if (!result.success) {
|
|
30
|
-
const issues = result.errors.map((e) => `[${e.key}] ${e.message}`).join('\n');
|
|
31
|
-
setState({ status: 'error', message: `Invalid payload:\n${issues}` });
|
|
32
|
-
exit(new Error('validation failed'));
|
|
33
|
-
return;
|
|
34
|
-
}
|
|
35
|
-
payload = result.data;
|
|
36
|
-
}
|
|
37
|
-
catch (err) {
|
|
38
|
-
setState({ status: 'error', message: `Error reading payload: ${err.message}` });
|
|
39
|
-
exit(new Error('read error'));
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
const texts = Object.entries(payload).map(([key, value]) => ({ key, value }));
|
|
43
|
-
if (!options.broadcast) {
|
|
44
|
-
const lines = [
|
|
45
|
-
`Dry run — would set ${texts.length} text records on ${ensName}:`,
|
|
46
|
-
'',
|
|
47
|
-
...texts.map((t) => ` setText("${t.key}", "${t.value}")`),
|
|
48
|
-
'',
|
|
49
|
-
'Run with --broadcast to submit on-chain.',
|
|
50
|
-
];
|
|
51
|
-
setState({ status: 'done', message: lines.join('\n') });
|
|
52
|
-
exit();
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
setState({ status: 'working', message: `Setting ${texts.length} text records on ${ensName}…` });
|
|
56
|
-
try {
|
|
57
|
-
const hash = await setEnsTextRecords(ensName, texts, options.privateKey);
|
|
58
|
-
setState({ status: 'done', message: `✅ Transaction submitted: ${hash}` });
|
|
59
|
-
exit();
|
|
60
|
-
}
|
|
61
|
-
catch (err) {
|
|
62
|
-
setState({ status: 'error', message: `Transaction failed: ${err.message}` });
|
|
63
|
-
exit(new Error('tx failed'));
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
run();
|
|
67
|
-
}, [exit, ensName, payloadFile, options]);
|
|
68
|
-
return (React.createElement(Box, { flexDirection: "column" },
|
|
69
|
-
state.status === 'idle' && React.createElement(Text, { color: "gray" }, "Preparing\u2026"),
|
|
70
|
-
state.status === 'working' && React.createElement(Text, { color: "cyan" }, state.message),
|
|
71
|
-
state.status === 'done' && React.createElement(Text, { color: "green" }, state.message),
|
|
72
|
-
state.status === 'error' && React.createElement(Text, { color: "red" },
|
|
73
|
-
"\u274C ",
|
|
74
|
-
state.message)));
|
|
75
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../../../src/commands/metadata/template.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAA;AAIzB,eAAO,MAAM,WAAW,mDAAmD,CAAA;AAE3E,MAAM,CAAC,OAAO,UAAU,gBAAgB,sBAMvC"}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { Text } from 'ink';
|
|
2
|
-
import React from 'react';
|
|
3
|
-
import { SCHEMA_MAP } from '@ens-node-metadata/schemas';
|
|
4
|
-
export const description = 'Generate starter ENS metadata payload template';
|
|
5
|
-
export default function MetadataTemplate() {
|
|
6
|
-
return (React.createElement(Text, null, JSON.stringify(SCHEMA_MAP.Agent, null, 2)));
|
|
7
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { z } from 'zod';
|
|
3
|
-
export declare const description = "Validate ENS metadata payload against agent schema";
|
|
4
|
-
export declare const args: z.ZodTuple<[z.ZodString], null>;
|
|
5
|
-
type Props = {
|
|
6
|
-
args: z.infer<typeof args>;
|
|
7
|
-
};
|
|
8
|
-
export default function MetadataValidate({ args: [file] }: Props): React.JSX.Element;
|
|
9
|
-
export {};
|
|
10
|
-
//# sourceMappingURL=validate.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../../src/commands/metadata/validate.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAIvB,eAAO,MAAM,WAAW,uDAAuD,CAAA;AAE/E,eAAO,MAAM,IAAI,iCAAiD,CAAA;AAElE,KAAK,KAAK,GAAG;IACX,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,CAAA;CAC3B,CAAA;AAED,MAAM,CAAC,OAAO,UAAU,gBAAgB,CAAC,EAAE,IAAI,EAAE,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,qBAwC/D"}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { readFileSync } from 'node:fs';
|
|
2
|
-
import { Box, Text, useApp } from 'ink';
|
|
3
|
-
import React from 'react';
|
|
4
|
-
import { z } from 'zod';
|
|
5
|
-
import { SCHEMA_MAP } from '@ens-node-metadata/schemas';
|
|
6
|
-
import { validateMetadataSchema } from '@ens-node-metadata/sdk';
|
|
7
|
-
export const description = 'Validate ENS metadata payload against agent schema';
|
|
8
|
-
export const args = z.tuple([z.string().describe('payload.json')]);
|
|
9
|
-
export default function MetadataValidate({ args: [file] }) {
|
|
10
|
-
const { exit } = useApp();
|
|
11
|
-
let fileError = null;
|
|
12
|
-
let result = null;
|
|
13
|
-
try {
|
|
14
|
-
const raw = JSON.parse(readFileSync(file, 'utf8'));
|
|
15
|
-
result = validateMetadataSchema(raw, SCHEMA_MAP.Agent);
|
|
16
|
-
}
|
|
17
|
-
catch (err) {
|
|
18
|
-
fileError = err.message;
|
|
19
|
-
}
|
|
20
|
-
React.useEffect(() => {
|
|
21
|
-
exit(fileError || (result && !result.success) ? new Error('validation failed') : undefined);
|
|
22
|
-
}, [exit, fileError, result]);
|
|
23
|
-
if (fileError) {
|
|
24
|
-
return React.createElement(Text, { color: "red" },
|
|
25
|
-
"\u274C Error reading file: ",
|
|
26
|
-
fileError);
|
|
27
|
-
}
|
|
28
|
-
if (result.success) {
|
|
29
|
-
return (React.createElement(Box, { flexDirection: "column" },
|
|
30
|
-
React.createElement(Text, { color: "green" }, "\u2705 Valid ENS agent metadata payload"),
|
|
31
|
-
React.createElement(Text, { color: "gray" },
|
|
32
|
-
" ",
|
|
33
|
-
Object.keys(result.data).length,
|
|
34
|
-
" text records")));
|
|
35
|
-
}
|
|
36
|
-
return (React.createElement(Box, { flexDirection: "column" },
|
|
37
|
-
React.createElement(Text, { color: "red" }, "\u274C Invalid agent metadata payload"),
|
|
38
|
-
result.errors.map(({ key, message }) => (React.createElement(Text, { key: key, color: "red" },
|
|
39
|
-
' ',
|
|
40
|
-
"[",
|
|
41
|
-
key,
|
|
42
|
-
"] ",
|
|
43
|
-
message)))));
|
|
44
|
-
}
|