@agentdomain/eliza-plugin 0.5.1 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/NOTICE ADDED
@@ -0,0 +1,5 @@
1
+ AgentDomain public developer tools and verified Base contracts
2
+ Copyright 2026 Md. Rakib
3
+
4
+ AgentDomain and related names and logos are trademarks or service marks of
5
+ their respective owner. This license does not grant trademark rights.
package/README.md CHANGED
@@ -10,10 +10,19 @@ The plugin gives Eliza agents a complete AgentDomain lifecycle surface:
10
10
 
11
11
  - Registration quote and x402 registration
12
12
  - Registry discovery
13
- - Agent email send/list/delete/batch, monthly usage, signed inbound webhooks, primary address updates, and Starter/Pro/Enterprise aliases
14
- - DNS management
13
+ - Agent email send/list/batch, monthly usage, signed inbound webhooks, primary address updates, and Starter/Pro/Enterprise aliases
14
+ - Typed DNS management for all 13 Spaceship-supported types, including capabilities, revision-safe batches, and BIND import/export
15
15
  - SSL repair/reconfiguration
16
16
  - RenewalVault status, funding, and auto-renew
17
- - Per-agent Premium Plan status, upgrades, and exact next-renewal tier selection
17
+ - Per-agent Premium Plan status and upgrades
18
18
 
19
19
  Configure `AGENTDOMAIN_API_URL` only if you need a custom endpoint. The default is `https://agentdomain.app/api/v1`.
20
+
21
+ Set `AGENTDOMAIN_BUILDER_CODE` to your public ERC-8021 app identifier whenever
22
+ the runtime can submit direct Base writes. The value is not a private key.
23
+ Eliza passes it to the SDK and uses it for post-registration auto-renew; missing
24
+ or invalid attribution stops the direct transaction before submission. Reads,
25
+ offchain signatures, Ethereum L1 ENS operations, and standard x402 v2 paid
26
+ requests are not changed.
27
+
28
+ Request the default base URL directly to retrieve AgentDomain's machine-readable API discovery metadata.
package/dist/index.d.ts CHANGED
@@ -11,6 +11,8 @@ interface Memory {
11
11
  text: string;
12
12
  };
13
13
  }
14
+ /** Builds the attributed direct calldata used by Eliza's post-registration auto-renew step. */
15
+ export declare function encodeElizaAutoRenewCalldata(tokenId: bigint, builderCode?: string): `0x${string}`;
14
16
  export declare const quoteRegistrationAction: {
15
17
  name: string;
16
18
  description: string;
@@ -234,6 +236,17 @@ export declare const listDnsAction: {
234
236
  data: import("@agentdomain/shared").DnsRecord[];
235
237
  }>;
236
238
  };
239
+ export declare const dnsCapabilitiesAction: {
240
+ name: string;
241
+ description: string;
242
+ similes: string[];
243
+ examples: never[];
244
+ validate: (runtime: IAgentRuntime) => Promise<boolean>;
245
+ handler: (runtime: IAgentRuntime, message: Memory) => Promise<{
246
+ text: string;
247
+ data: import("@agentdomain/shared").DnsCapabilities;
248
+ }>;
249
+ };
237
250
  export declare const createDnsAction: {
238
251
  name: string;
239
252
  description: string;
@@ -269,6 +282,42 @@ export declare const deleteDnsAction: {
269
282
  };
270
283
  }>;
271
284
  };
285
+ export declare const changeDnsRecordsAction: {
286
+ name: string;
287
+ description: string;
288
+ similes: string[];
289
+ examples: never[];
290
+ validate: (runtime: IAgentRuntime) => Promise<boolean>;
291
+ handler: (runtime: IAgentRuntime, message: Memory) => Promise<{
292
+ text: string;
293
+ data: import("@agentdomain/shared").DnsChangePreview;
294
+ }>;
295
+ };
296
+ export declare const importDnsZoneAction: {
297
+ name: string;
298
+ description: string;
299
+ similes: string[];
300
+ examples: never[];
301
+ validate: (runtime: IAgentRuntime) => Promise<boolean>;
302
+ handler: (runtime: IAgentRuntime, message: Memory) => Promise<{
303
+ text: string;
304
+ data: import("@agentdomain/shared").DnsChangePreview;
305
+ }>;
306
+ };
307
+ export declare const exportDnsZoneAction: {
308
+ name: string;
309
+ description: string;
310
+ similes: string[];
311
+ examples: never[];
312
+ validate: (runtime: IAgentRuntime) => Promise<boolean>;
313
+ handler: (runtime: IAgentRuntime, message: Memory) => Promise<{
314
+ text: string;
315
+ data: {
316
+ format: string;
317
+ zone: string;
318
+ };
319
+ }>;
320
+ };
272
321
  export declare const servicePlanStatusAction: {
273
322
  name: string;
274
323
  description: string;
@@ -512,6 +561,16 @@ export declare const agentDomainPlugin: {
512
561
  text: string;
513
562
  data: import("@agentdomain/shared").DnsRecord[];
514
563
  }>;
564
+ } | {
565
+ name: string;
566
+ description: string;
567
+ similes: string[];
568
+ examples: never[];
569
+ validate: (runtime: IAgentRuntime) => Promise<boolean>;
570
+ handler: (runtime: IAgentRuntime, message: Memory) => Promise<{
571
+ text: string;
572
+ data: import("@agentdomain/shared").DnsCapabilities;
573
+ }>;
515
574
  } | {
516
575
  name: string;
517
576
  description: string;
@@ -534,6 +593,29 @@ export declare const agentDomainPlugin: {
534
593
  success: boolean;
535
594
  };
536
595
  }>;
596
+ } | {
597
+ name: string;
598
+ description: string;
599
+ similes: string[];
600
+ examples: never[];
601
+ validate: (runtime: IAgentRuntime) => Promise<boolean>;
602
+ handler: (runtime: IAgentRuntime, message: Memory) => Promise<{
603
+ text: string;
604
+ data: import("@agentdomain/shared").DnsChangePreview;
605
+ }>;
606
+ } | {
607
+ name: string;
608
+ description: string;
609
+ similes: string[];
610
+ examples: never[];
611
+ validate: (runtime: IAgentRuntime) => Promise<boolean>;
612
+ handler: (runtime: IAgentRuntime, message: Memory) => Promise<{
613
+ text: string;
614
+ data: {
615
+ format: string;
616
+ zone: string;
617
+ };
618
+ }>;
537
619
  } | {
538
620
  name: string;
539
621
  description: string;
package/dist/index.js CHANGED
@@ -1,20 +1,29 @@
1
- import { AgentDomain } from '@agentdomain/sdk';
1
+ import { AgentDomain, encodeSetAutoRenewCalldata } from '@agentdomain/sdk';
2
2
  import { AGENTDOMAIN_API_BASE_URL, SERVICE_PLAN_KEYS, SUPPORTED_TLDS, } from '@agentdomain/shared/constants';
3
- import { createPublicClient, createWalletClient, http, } from 'viem';
3
+ import { DNS_RECORD_TYPES, dnsRecordSchema as sharedDnsRecordSchema, } from '@agentdomain/shared';
4
+ import { createPublicClient, createWalletClient, http } from 'viem';
4
5
  import { privateKeyToAccount } from 'viem/accounts';
5
6
  import { base, baseSepolia } from 'viem/chains';
6
7
  import { z } from 'zod';
8
+ /** Builds the attributed direct calldata used by Eliza's post-registration auto-renew step. */
9
+ export function encodeElizaAutoRenewCalldata(tokenId, builderCode) {
10
+ if (!builderCode) {
11
+ throw new Error('AGENTDOMAIN_BUILDER_CODE is required for attributed direct Base transactions.');
12
+ }
13
+ return encodeSetAutoRenewCalldata(tokenId, true, builderCode);
14
+ }
7
15
  function getClients(runtime, opts = {}) {
8
16
  const apiUrl = runtime.getSetting('AGENTDOMAIN_API_URL') ?? AGENTDOMAIN_API_BASE_URL;
9
17
  const apiKey = runtime.getSetting('AGENTDOMAIN_API_KEY');
10
18
  const pk = runtime.getSetting('AGENT_PRIVATE_KEY');
11
19
  const rpc = runtime.getSetting('BASE_RPC_URL') ?? 'https://mainnet.base.org';
12
20
  const network = runtime.getSetting('AGENTDOMAIN_NETWORK') ?? 'base';
21
+ const builderCode = runtime.getSetting('AGENTDOMAIN_BUILDER_CODE');
13
22
  const chain = network === 'base-sepolia' ? baseSepolia : base;
14
23
  if (!pk) {
15
24
  if (opts.requireWallet)
16
25
  throw new Error('AGENT_PRIVATE_KEY not set');
17
- const ad = new AgentDomain({ apiUrl, apiKey, network });
26
+ const ad = new AgentDomain({ apiUrl, apiKey, network, builderCode });
18
27
  return { ad, account: null, walletClient: null, publicClient: null, network, chain, rpc };
19
28
  }
20
29
  const account = privateKeyToAccount(pk);
@@ -26,6 +35,7 @@ function getClients(runtime, opts = {}) {
26
35
  network,
27
36
  walletClient: walletClient,
28
37
  publicClient: publicClient,
38
+ builderCode,
29
39
  });
30
40
  return { ad, account, walletClient, publicClient, network, chain, rpc };
31
41
  }
@@ -47,9 +57,9 @@ const registerSchema = z.object({
47
57
  premiumPlan: z.enum(SERVICE_PLAN_KEYS).default('included'),
48
58
  });
49
59
  const dnsRecordSchema = z.object({
50
- type: z.enum(['A', 'AAAA', 'ALIAS', 'CNAME', 'MX', 'TXT', 'NS', 'SRV']),
60
+ type: z.enum(DNS_RECORD_TYPES),
51
61
  name: z.string(),
52
- value: z.string(),
62
+ value: z.string().min(1).max(65_535),
53
63
  ttl: z.number().int().min(60).max(3600).default(3600),
54
64
  priority: z.number().int().min(0).optional(),
55
65
  });
@@ -111,20 +121,46 @@ function parsePlan(text) {
111
121
  }
112
122
  function parseDnsRecord(text) {
113
123
  const lower = text.toLowerCase();
114
- const typeMatch = text.match(/\b(A|AAAA|ALIAS|CNAME|MX|TXT|NS|SRV)\b/i);
124
+ const typeMatch = text.match(/\b(A|AAAA|ALIAS|CAA|CNAME|HTTPS|MX|NS|PTR|SRV|SVCB|TLSA|TXT)\b/i);
115
125
  const nameMatch = text.match(/\bname[:=]\s*([^\s]+)/i);
116
- const valueMatch = text.match(/\bvalue[:=]\s*([^\s]+)/i);
126
+ const valueMatch = text.match(/\bvalue[:=]\s*(.+?)(?=\s+\b(?:ttl|priority)[:=]|$)/i);
117
127
  const ttlMatch = text.match(/\bttl[:=]\s*(\d+)/i);
118
128
  const priorityMatch = text.match(/\bpriority[:=]\s*(\d+)/i);
119
129
  const parsed = dnsRecordSchema.parse({
120
130
  type: typeMatch?.[1]?.toUpperCase() ?? (lower.includes('txt') ? 'TXT' : 'A'),
121
131
  name: nameMatch?.[1] ?? '@',
122
- value: valueMatch?.[1] ?? text.match(/\b(?:\d{1,3}\.){3}\d{1,3}\b/)?.[0] ?? '',
132
+ value: valueMatch?.[1]?.trim() ?? text.match(/\b(?:\d{1,3}\.){3}\d{1,3}\b/)?.[0] ?? '',
123
133
  ttl: ttlMatch ? Number(ttlMatch[1]) : 3600,
124
134
  priority: priorityMatch ? Number(priorityMatch[1]) : undefined,
125
135
  });
126
136
  return parsed;
127
137
  }
138
+ function parseDnsRecordsJson(text) {
139
+ const fenced = text.match(/```(?:json)?\s*([\s\S]*?)```/i)?.[1];
140
+ const json = fenced ?? text.slice(text.indexOf('['), text.lastIndexOf(']') + 1);
141
+ if (!json)
142
+ throw new Error('A JSON array of DNS records is required');
143
+ return z.array(sharedDnsRecordSchema).min(1).max(200).parse(JSON.parse(json));
144
+ }
145
+ function parseZoneFile(text) {
146
+ const fenced = text.match(/```(?:bind|zone|dns)?\s*([\s\S]*?)```/i)?.[1];
147
+ if (!fenced?.trim())
148
+ throw new Error('Put the BIND zone records inside a fenced code block');
149
+ return fenced.trim();
150
+ }
151
+ function parseDnsApplyOptions(text) {
152
+ const lower = text.toLowerCase();
153
+ return {
154
+ mode: lower.includes('replace') ? 'replace' : 'merge',
155
+ dryRun: !/\bapply\b/i.test(text),
156
+ baseRevision: text.match(/\bbaseRevision[:=]\s*([a-f0-9]{64})/i)?.[1],
157
+ };
158
+ }
159
+ function requireDnsRevision(value) {
160
+ if (!value)
161
+ throw new Error('Apply requires baseRevision from a fresh DNS preview');
162
+ return value;
163
+ }
128
164
  function parseEmailUsername(text) {
129
165
  const explicit = text.match(/\b(?:email\s+username|primary\s+email|username|alias)[:=]?\s*([a-z0-9._+-]{1,64})/i)?.[1] ?? text.match(EMAIL_PATTERN)?.[0]?.split('@')[0];
130
166
  const username = explicit?.trim().toLowerCase();
@@ -178,8 +214,10 @@ export const registerIdentityAction = {
178
214
  handler: async (runtime, message) => {
179
215
  const params = parseParamsFromText(message.content.text);
180
216
  const validated = registerSchema.parse(params);
181
- const { ad, account, walletClient, chain } = getClients(runtime, { requireWallet: true });
182
- if (!account || !walletClient)
217
+ const { ad, account, walletClient, publicClient, chain } = getClients(runtime, {
218
+ requireWallet: true,
219
+ });
220
+ if (!account || !walletClient || !publicClient)
183
221
  throw new Error('AGENT_PRIVATE_KEY not set');
184
222
  const result = await ad.register({
185
223
  ...validated,
@@ -191,23 +229,22 @@ export const registerIdentityAction = {
191
229
  const vaultAddress = runtime.getSetting('RENEWAL_VAULT_ADDRESS');
192
230
  if (vaultAddress) {
193
231
  try {
194
- const txHash = await walletClient.writeContract({
195
- address: vaultAddress,
196
- abi: [
197
- {
198
- type: 'function',
199
- name: 'setAutoRenew',
200
- inputs: [
201
- { name: 'tokenId', type: 'uint256' },
202
- { name: 'enabled', type: 'bool' },
203
- ],
204
- },
205
- ],
206
- functionName: 'setAutoRenew',
207
- args: [BigInt(result.nftTokenId), true],
232
+ const txHash = await walletClient.sendTransaction({
233
+ to: vaultAddress,
234
+ data: encodeElizaAutoRenewCalldata(BigInt(result.nftTokenId), runtime.getSetting('AGENTDOMAIN_BUILDER_CODE')),
208
235
  chain,
209
236
  account,
210
237
  });
238
+ let receipt;
239
+ try {
240
+ receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
241
+ }
242
+ catch (e) {
243
+ throw new Error(`Auto-renew transaction ${txHash} was submitted but confirmation failed or remained pending: ${String(e)}`);
244
+ }
245
+ if (receipt.status !== 'success') {
246
+ throw new Error(`Auto-renew transaction ${txHash} confirmed with status ${receipt.status}; auto-renew was not enabled.`);
247
+ }
211
248
  autoRenewMsg = ` Auto-renew enabled via tx ${txHash}.`;
212
249
  }
213
250
  catch (e) {
@@ -426,6 +463,7 @@ export const enableAutoRenewAction = {
426
463
  const agentId = requireAgentId(message.content.text);
427
464
  const result = await ad.setAutoRenew(agentId, true, {
428
465
  renewalVaultAddress: runtime.getSetting('RENEWAL_VAULT_ADDRESS'),
466
+ waitForReceipt: true,
429
467
  });
430
468
  return { text: `Auto-renew enabled for token #${result.tokenId}.`, data: result };
431
469
  },
@@ -461,6 +499,21 @@ export const listDnsAction = {
461
499
  return { text: `Found ${records.length} DNS records.`, data: records };
462
500
  },
463
501
  };
502
+ export const dnsCapabilitiesAction = {
503
+ name: 'GET_DNS_CAPABILITIES',
504
+ description: 'Get AgentDomain DNS record types, validation fields, limits, and provider warnings.',
505
+ similes: ['DNS_CAPABILITIES', 'DNS_TYPES', 'DNS_LIMITS'],
506
+ examples: [],
507
+ validate: async (runtime) => Boolean(runtime.getSetting('AGENT_PRIVATE_KEY') || runtime.getSetting('AGENTDOMAIN_API_KEY')),
508
+ handler: async (runtime, message) => {
509
+ const { ad } = getClients(runtime);
510
+ const result = await ad.getDnsCapabilities(requireAgentId(message.content.text));
511
+ return {
512
+ text: `AgentDomain supports ${result.supportedTypes.length} Spaceship DNS record types.`,
513
+ data: result,
514
+ };
515
+ },
516
+ };
464
517
  export const createDnsAction = {
465
518
  name: 'CREATE_DNS_RECORD',
466
519
  description: 'Create a user-managed DNS record. Use text like: agentId type A name @ value 1.2.3.4.',
@@ -510,6 +563,58 @@ export const deleteDnsAction = {
510
563
  return { text: `Deleted DNS record ${recordId}.`, data: result };
511
564
  },
512
565
  };
566
+ export const changeDnsRecordsAction = {
567
+ name: 'CHANGE_DNS_RECORDS',
568
+ description: 'Preview or apply a revision-protected DNS batch from a JSON array of structured records.',
569
+ similes: ['BATCH_DNS', 'PREVIEW_DNS_CHANGES', 'APPLY_DNS_CHANGES'],
570
+ examples: [],
571
+ validate: async (runtime) => Boolean(runtime.getSetting('AGENT_PRIVATE_KEY') || runtime.getSetting('AGENTDOMAIN_API_KEY')),
572
+ handler: async (runtime, message) => {
573
+ const { ad } = getClients(runtime);
574
+ const agentId = requireAgentId(message.content.text);
575
+ const records = parseDnsRecordsJson(message.content.text);
576
+ const options = parseDnsApplyOptions(message.content.text);
577
+ const result = options.dryRun
578
+ ? await ad.previewDnsBatch(agentId, records, options.mode)
579
+ : await ad.applyDnsBatch(agentId, records, requireDnsRevision(options.baseRevision), options.mode);
580
+ return {
581
+ text: options.dryRun ? 'DNS preview generated.' : 'DNS change set applied.',
582
+ data: result,
583
+ };
584
+ },
585
+ };
586
+ export const importDnsZoneAction = {
587
+ name: 'IMPORT_DNS_ZONE',
588
+ description: 'Preview or apply a validated BIND DNS zone import.',
589
+ similes: ['DNS_ZONE_IMPORT', 'IMPORT_BIND_ZONE'],
590
+ examples: [],
591
+ validate: async (runtime) => Boolean(runtime.getSetting('AGENT_PRIVATE_KEY') || runtime.getSetting('AGENTDOMAIN_API_KEY')),
592
+ handler: async (runtime, message) => {
593
+ const { ad } = getClients(runtime);
594
+ const agentId = requireAgentId(message.content.text);
595
+ const zoneFile = parseZoneFile(message.content.text);
596
+ const options = parseDnsApplyOptions(message.content.text);
597
+ const result = options.dryRun
598
+ ? await ad.previewDnsImport(agentId, zoneFile, options.mode)
599
+ : await ad.applyDnsImport(agentId, zoneFile, requireDnsRevision(options.baseRevision), options.mode);
600
+ return {
601
+ text: options.dryRun ? 'DNS import preview generated.' : 'DNS zone import applied.',
602
+ data: result,
603
+ };
604
+ },
605
+ };
606
+ export const exportDnsZoneAction = {
607
+ name: 'EXPORT_DNS_ZONE',
608
+ description: 'Export AgentDomain DNS records as a standard BIND zone file.',
609
+ similes: ['DNS_ZONE_EXPORT', 'EXPORT_BIND_ZONE'],
610
+ examples: [],
611
+ validate: async (runtime) => Boolean(runtime.getSetting('AGENT_PRIVATE_KEY') || runtime.getSetting('AGENTDOMAIN_API_KEY')),
612
+ handler: async (runtime, message) => {
613
+ const { ad } = getClients(runtime);
614
+ const zone = await ad.exportDnsZone(requireAgentId(message.content.text), /\b(?:all|complete)\b/i.test(message.content.text) ? 'all' : 'user');
615
+ return { text: zone, data: { format: 'bind', zone } };
616
+ },
617
+ };
513
618
  export const servicePlanStatusAction = {
514
619
  name: 'GET_SERVICE_PLAN',
515
620
  description: 'Get an agent Premium Plan, limits, current period, and billing state.',
@@ -607,10 +712,14 @@ export const agentDomainPlugin = {
607
712
  fundRenewalAction,
608
713
  enableAutoRenewAction,
609
714
  reconfigureSslAction,
715
+ dnsCapabilitiesAction,
610
716
  listDnsAction,
611
717
  createDnsAction,
612
718
  updateDnsAction,
613
719
  deleteDnsAction,
720
+ changeDnsRecordsAction,
721
+ importDnsZoneAction,
722
+ exportDnsZoneAction,
614
723
  servicePlanStatusAction,
615
724
  setRegistryVisibilityAction,
616
725
  scheduleServicePlanRenewalAction,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentdomain/eliza-plugin",
3
- "version": "0.5.1",
3
+ "version": "0.7.0",
4
4
  "description": "ElizaOS plugin for AgentDomain - give your Eliza agent a complete identity stack",
5
5
  "license": "Apache-2.0",
6
6
  "repository": "https://github.com/0xmdrakib/AgentDomain.git",
@@ -18,6 +18,8 @@
18
18
  "files": [
19
19
  "dist",
20
20
  "README.md",
21
+ "LICENSE",
22
+ "NOTICE",
21
23
  "package.json"
22
24
  ],
23
25
  "publishConfig": {
@@ -26,8 +28,8 @@
26
28
  "dependencies": {
27
29
  "viem": "^2.55.2",
28
30
  "zod": "^3.24.1",
29
- "@agentdomain/sdk": "^0.5.1",
30
- "@agentdomain/shared": "^0.5.1"
31
+ "@agentdomain/sdk": "^0.7.0",
32
+ "@agentdomain/shared": "^0.7.0"
31
33
  },
32
34
  "peerDependencies": {
33
35
  "@elizaos/core": "^1.0.0"
@@ -37,6 +39,7 @@
37
39
  },
38
40
  "scripts": {
39
41
  "build": "tsc",
42
+ "test": "pnpm --filter @agentdomain/sdk build && pnpm run build && node --test test/*.test.mjs",
40
43
  "typecheck": "tsc --noEmit",
41
44
  "lint": "echo \"no lint\""
42
45
  }