@agentdomain/eliza-plugin 0.2.1 → 0.4.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/LICENSE +202 -21
- package/README.md +1 -1
- package/dist/index.d.ts +79 -0
- package/dist/index.js +284 -159
- package/package.json +7 -4
package/LICENSE
CHANGED
|
@@ -1,21 +1,202 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
1
|
+
|
|
2
|
+
Apache License
|
|
3
|
+
Version 2.0, January 2004
|
|
4
|
+
http://www.apache.org/licenses/
|
|
5
|
+
|
|
6
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
7
|
+
|
|
8
|
+
1. Definitions.
|
|
9
|
+
|
|
10
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
11
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
12
|
+
|
|
13
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
14
|
+
the copyright owner that is granting the License.
|
|
15
|
+
|
|
16
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
17
|
+
other entities that control, are controlled by, or are under common
|
|
18
|
+
control with that entity. For the purposes of this definition,
|
|
19
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
20
|
+
direction or management of such entity, whether by contract or
|
|
21
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
22
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
23
|
+
|
|
24
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
25
|
+
exercising permissions granted by this License.
|
|
26
|
+
|
|
27
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
28
|
+
including but not limited to software source code, documentation
|
|
29
|
+
source, and configuration files.
|
|
30
|
+
|
|
31
|
+
"Object" form shall mean any form resulting from mechanical
|
|
32
|
+
transformation or translation of a Source form, including but
|
|
33
|
+
not limited to compiled object code, generated documentation,
|
|
34
|
+
and conversions to other media types.
|
|
35
|
+
|
|
36
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
37
|
+
Object form, made available under the License, as indicated by a
|
|
38
|
+
copyright notice that is included in or attached to the work
|
|
39
|
+
(an example is provided in the Appendix below).
|
|
40
|
+
|
|
41
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
42
|
+
form, that is based on (or derived from) the Work and for which the
|
|
43
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
44
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
45
|
+
of this License, Derivative Works shall not include works that remain
|
|
46
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
47
|
+
the Work and Derivative Works thereof.
|
|
48
|
+
|
|
49
|
+
"Contribution" shall mean any work of authorship, including
|
|
50
|
+
the original version of the Work and any modifications or additions
|
|
51
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
52
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
53
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
54
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
55
|
+
means any form of electronic, verbal, or written communication sent
|
|
56
|
+
to the Licensor or its representatives, including but not limited to
|
|
57
|
+
communication on electronic mailing lists, source code control systems,
|
|
58
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
59
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
60
|
+
excluding communication that is conspicuously marked or otherwise
|
|
61
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
62
|
+
|
|
63
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
64
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
65
|
+
subsequently incorporated within the Work.
|
|
66
|
+
|
|
67
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
68
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
69
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
70
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
71
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
72
|
+
Work and such Derivative Works in Source or Object form.
|
|
73
|
+
|
|
74
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
75
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
76
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
77
|
+
(except as stated in this section) patent license to make, have made,
|
|
78
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
79
|
+
where such license applies only to those patent claims licensable
|
|
80
|
+
by such Contributor that are necessarily infringed by their
|
|
81
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
82
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
83
|
+
institute patent litigation against any entity (including a
|
|
84
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
85
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
86
|
+
or contributory patent infringement, then any patent licenses
|
|
87
|
+
granted to You under this License for that Work shall terminate
|
|
88
|
+
as of the date such litigation is filed.
|
|
89
|
+
|
|
90
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
91
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
92
|
+
modifications, and in Source or Object form, provided that You
|
|
93
|
+
meet the following conditions:
|
|
94
|
+
|
|
95
|
+
(a) You must give any other recipients of the Work or
|
|
96
|
+
Derivative Works a copy of this License; and
|
|
97
|
+
|
|
98
|
+
(b) You must cause any modified files to carry prominent notices
|
|
99
|
+
stating that You changed the files; and
|
|
100
|
+
|
|
101
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
102
|
+
that You distribute, all copyright, patent, trademark, and
|
|
103
|
+
attribution notices from the Source form of the Work,
|
|
104
|
+
excluding those notices that do not pertain to any part of
|
|
105
|
+
the Derivative Works; and
|
|
106
|
+
|
|
107
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
108
|
+
distribution, then any Derivative Works that You distribute must
|
|
109
|
+
include a readable copy of the attribution notices contained
|
|
110
|
+
within such NOTICE file, excluding those notices that do not
|
|
111
|
+
pertain to any part of the Derivative Works, in at least one
|
|
112
|
+
of the following places: within a NOTICE text file distributed
|
|
113
|
+
as part of the Derivative Works; within the Source form or
|
|
114
|
+
documentation, if provided along with the Derivative Works; or,
|
|
115
|
+
within a display generated by the Derivative Works, if and
|
|
116
|
+
wherever such third-party notices normally appear. The contents
|
|
117
|
+
of the NOTICE file are for informational purposes only and
|
|
118
|
+
do not modify the License. You may add Your own attribution
|
|
119
|
+
notices within Derivative Works that You distribute, alongside
|
|
120
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
121
|
+
that such additional attribution notices cannot be construed
|
|
122
|
+
as modifying the License.
|
|
123
|
+
|
|
124
|
+
You may add Your own copyright statement to Your modifications and
|
|
125
|
+
may provide additional or different license terms and conditions
|
|
126
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
127
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
128
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
129
|
+
the conditions stated in this License.
|
|
130
|
+
|
|
131
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
132
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
133
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
134
|
+
this License, without any additional terms or conditions.
|
|
135
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
136
|
+
the terms of any separate license agreement you may have executed
|
|
137
|
+
with Licensor regarding such Contributions.
|
|
138
|
+
|
|
139
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
140
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
141
|
+
except as required for reasonable and customary use in describing the
|
|
142
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
143
|
+
|
|
144
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
145
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
146
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
147
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
148
|
+
implied, including, without limitation, any warranties or conditions
|
|
149
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
150
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
151
|
+
appropriateness of using or redistributing the Work and assume any
|
|
152
|
+
risks associated with Your exercise of permissions under this License.
|
|
153
|
+
|
|
154
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
155
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
156
|
+
unless required by applicable law (such as deliberate and grossly
|
|
157
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
158
|
+
liable to You for damages, including any direct, indirect, special,
|
|
159
|
+
incidental, or consequential damages of any character arising as a
|
|
160
|
+
result of this License or out of the use or inability to use the
|
|
161
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
162
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
163
|
+
other commercial damages or losses), even if such Contributor
|
|
164
|
+
has been advised of the possibility of such damages.
|
|
165
|
+
|
|
166
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
167
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
168
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
169
|
+
or other liability obligations and/or rights consistent with this
|
|
170
|
+
License. However, in accepting such obligations, You may act only
|
|
171
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
172
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
173
|
+
defend, and hold each Contributor harmless for any liability
|
|
174
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
175
|
+
of your accepting any such warranty or additional liability.
|
|
176
|
+
|
|
177
|
+
END OF TERMS AND CONDITIONS
|
|
178
|
+
|
|
179
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
180
|
+
|
|
181
|
+
To apply the Apache License to your work, attach the following
|
|
182
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
183
|
+
replaced with your own identifying information. (Don't include
|
|
184
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
185
|
+
comment syntax for the file format. We also recommend that a
|
|
186
|
+
file or class name and description of purpose be included on the
|
|
187
|
+
same "printed page" as the copyright notice for easier
|
|
188
|
+
identification within third-party archives.
|
|
189
|
+
|
|
190
|
+
Copyright [yyyy] [name of copyright owner]
|
|
191
|
+
|
|
192
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
193
|
+
you may not use this file except in compliance with the License.
|
|
194
|
+
You may obtain a copy of the License at
|
|
195
|
+
|
|
196
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
197
|
+
|
|
198
|
+
Unless required by applicable law or agreed to in writing, software
|
|
199
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
200
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
201
|
+
See the License for the specific language governing permissions and
|
|
202
|
+
limitations under the License.
|
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ 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, primary address
|
|
13
|
+
- Agent email send/list/batch, monthly usage, signed inbound webhooks, primary address updates, and Starter/Pro/Enterprise aliases
|
|
14
14
|
- DNS management
|
|
15
15
|
- SSL repair/reconfiguration
|
|
16
16
|
- RenewalVault status, funding, and auto-renew
|
package/dist/index.d.ts
CHANGED
|
@@ -81,6 +81,47 @@ export declare const sendEmailAction: {
|
|
|
81
81
|
data: import("@agentdomain/sdk").EmailResult;
|
|
82
82
|
}>;
|
|
83
83
|
};
|
|
84
|
+
export declare const emailUsageAction: {
|
|
85
|
+
name: string;
|
|
86
|
+
description: string;
|
|
87
|
+
similes: string[];
|
|
88
|
+
examples: never[];
|
|
89
|
+
validate: (runtime: IAgentRuntime) => Promise<boolean>;
|
|
90
|
+
handler: (runtime: IAgentRuntime, message: Memory) => Promise<{
|
|
91
|
+
text: string;
|
|
92
|
+
data: import("@agentdomain/sdk").EmailUsageResult;
|
|
93
|
+
}>;
|
|
94
|
+
};
|
|
95
|
+
export declare const configureEmailWebhookAction: {
|
|
96
|
+
name: string;
|
|
97
|
+
description: string;
|
|
98
|
+
similes: string[];
|
|
99
|
+
examples: never[];
|
|
100
|
+
validate: (runtime: IAgentRuntime) => Promise<boolean>;
|
|
101
|
+
handler: (runtime: IAgentRuntime, message: Memory) => Promise<{
|
|
102
|
+
text: string;
|
|
103
|
+
data: {
|
|
104
|
+
webhook: import("@agentdomain/sdk").EmailWebhookConfig;
|
|
105
|
+
signingSecret?: string;
|
|
106
|
+
};
|
|
107
|
+
}>;
|
|
108
|
+
};
|
|
109
|
+
export declare const sendEmailBatchAction: {
|
|
110
|
+
name: string;
|
|
111
|
+
description: string;
|
|
112
|
+
similes: string[];
|
|
113
|
+
examples: never[];
|
|
114
|
+
validate: (runtime: IAgentRuntime) => Promise<boolean>;
|
|
115
|
+
handler: (runtime: IAgentRuntime, message: Memory) => Promise<{
|
|
116
|
+
text: string;
|
|
117
|
+
data: {
|
|
118
|
+
batchId: string;
|
|
119
|
+
status: string;
|
|
120
|
+
jobs: unknown[];
|
|
121
|
+
errors: unknown[];
|
|
122
|
+
};
|
|
123
|
+
}>;
|
|
124
|
+
};
|
|
84
125
|
export declare const updatePrimaryEmailAction: {
|
|
85
126
|
name: string;
|
|
86
127
|
description: string;
|
|
@@ -315,6 +356,44 @@ export declare const agentDomainPlugin: {
|
|
|
315
356
|
text: string;
|
|
316
357
|
data: import("@agentdomain/sdk").EmailResult;
|
|
317
358
|
}>;
|
|
359
|
+
} | {
|
|
360
|
+
name: string;
|
|
361
|
+
description: string;
|
|
362
|
+
similes: string[];
|
|
363
|
+
examples: never[];
|
|
364
|
+
validate: (runtime: IAgentRuntime) => Promise<boolean>;
|
|
365
|
+
handler: (runtime: IAgentRuntime, message: Memory) => Promise<{
|
|
366
|
+
text: string;
|
|
367
|
+
data: import("@agentdomain/sdk").EmailUsageResult;
|
|
368
|
+
}>;
|
|
369
|
+
} | {
|
|
370
|
+
name: string;
|
|
371
|
+
description: string;
|
|
372
|
+
similes: string[];
|
|
373
|
+
examples: never[];
|
|
374
|
+
validate: (runtime: IAgentRuntime) => Promise<boolean>;
|
|
375
|
+
handler: (runtime: IAgentRuntime, message: Memory) => Promise<{
|
|
376
|
+
text: string;
|
|
377
|
+
data: {
|
|
378
|
+
webhook: import("@agentdomain/sdk").EmailWebhookConfig;
|
|
379
|
+
signingSecret?: string;
|
|
380
|
+
};
|
|
381
|
+
}>;
|
|
382
|
+
} | {
|
|
383
|
+
name: string;
|
|
384
|
+
description: string;
|
|
385
|
+
similes: string[];
|
|
386
|
+
examples: never[];
|
|
387
|
+
validate: (runtime: IAgentRuntime) => Promise<boolean>;
|
|
388
|
+
handler: (runtime: IAgentRuntime, message: Memory) => Promise<{
|
|
389
|
+
text: string;
|
|
390
|
+
data: {
|
|
391
|
+
batchId: string;
|
|
392
|
+
status: string;
|
|
393
|
+
jobs: unknown[];
|
|
394
|
+
errors: unknown[];
|
|
395
|
+
};
|
|
396
|
+
}>;
|
|
318
397
|
} | {
|
|
319
398
|
name: string;
|
|
320
399
|
description: string;
|
package/dist/index.js
CHANGED
|
@@ -1,24 +1,37 @@
|
|
|
1
|
-
import { AgentDomain } from
|
|
2
|
-
import { AGENTDOMAIN_API_BASE_URL, SERVICE_PLAN_KEYS, SUPPORTED_TLDS, } from
|
|
3
|
-
import { createPublicClient, createWalletClient, http, } from
|
|
4
|
-
import { privateKeyToAccount } from
|
|
5
|
-
import { base, baseSepolia } from
|
|
6
|
-
import { z } from
|
|
1
|
+
import { AgentDomain } from "@agentdomain/sdk";
|
|
2
|
+
import { AGENTDOMAIN_API_BASE_URL, SERVICE_PLAN_KEYS, SUPPORTED_TLDS, } from "@agentdomain/shared/constants";
|
|
3
|
+
import { createPublicClient, createWalletClient, http, } from "viem";
|
|
4
|
+
import { privateKeyToAccount } from "viem/accounts";
|
|
5
|
+
import { base, baseSepolia } from "viem/chains";
|
|
6
|
+
import { z } from "zod";
|
|
7
7
|
function getClients(runtime, opts = {}) {
|
|
8
|
-
const apiUrl = runtime.getSetting(
|
|
9
|
-
const apiKey = runtime.getSetting(
|
|
10
|
-
const pk = runtime.getSetting(
|
|
11
|
-
const rpc = runtime.getSetting(
|
|
12
|
-
const network = runtime.getSetting(
|
|
13
|
-
|
|
8
|
+
const apiUrl = runtime.getSetting("AGENTDOMAIN_API_URL") ?? AGENTDOMAIN_API_BASE_URL;
|
|
9
|
+
const apiKey = runtime.getSetting("AGENTDOMAIN_API_KEY");
|
|
10
|
+
const pk = runtime.getSetting("AGENT_PRIVATE_KEY");
|
|
11
|
+
const rpc = runtime.getSetting("BASE_RPC_URL") ?? "https://mainnet.base.org";
|
|
12
|
+
const network = runtime.getSetting("AGENTDOMAIN_NETWORK") ??
|
|
13
|
+
"base";
|
|
14
|
+
const chain = network === "base-sepolia" ? baseSepolia : base;
|
|
14
15
|
if (!pk) {
|
|
15
16
|
if (opts.requireWallet)
|
|
16
|
-
throw new Error(
|
|
17
|
+
throw new Error("AGENT_PRIVATE_KEY not set");
|
|
17
18
|
const ad = new AgentDomain({ apiUrl, apiKey, network });
|
|
18
|
-
return {
|
|
19
|
+
return {
|
|
20
|
+
ad,
|
|
21
|
+
account: null,
|
|
22
|
+
walletClient: null,
|
|
23
|
+
publicClient: null,
|
|
24
|
+
network,
|
|
25
|
+
chain,
|
|
26
|
+
rpc,
|
|
27
|
+
};
|
|
19
28
|
}
|
|
20
29
|
const account = privateKeyToAccount(pk);
|
|
21
|
-
const walletClient = createWalletClient({
|
|
30
|
+
const walletClient = createWalletClient({
|
|
31
|
+
account,
|
|
32
|
+
chain,
|
|
33
|
+
transport: http(rpc),
|
|
34
|
+
});
|
|
22
35
|
const publicClient = createPublicClient({ chain, transport: http(rpc) });
|
|
23
36
|
const ad = new AgentDomain({
|
|
24
37
|
apiUrl,
|
|
@@ -29,7 +42,7 @@ function getClients(runtime, opts = {}) {
|
|
|
29
42
|
});
|
|
30
43
|
return { ad, account, walletClient, publicClient, network, chain, rpc };
|
|
31
44
|
}
|
|
32
|
-
const TLD_PATTERN = new RegExp(String.raw `([a-z0-9-]{3,63})\.([a-z]{2,20})\b`,
|
|
45
|
+
const TLD_PATTERN = new RegExp(String.raw `([a-z0-9-]{3,63})\.([a-z]{2,20})\b`, "i");
|
|
33
46
|
const UUID_PATTERN = /[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}/i;
|
|
34
47
|
const AMOUNT_PATTERN = /\$?\s*(\d+(?:\.\d{1,6})?)\s*(?:usdc)?/i;
|
|
35
48
|
const EMAIL_PATTERN = /[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}/i;
|
|
@@ -37,7 +50,7 @@ const EMAIL_GLOBAL_PATTERN = /[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}/gi;
|
|
|
37
50
|
const EMAIL_USERNAME_PATTERN = /^[a-z0-9](?:[a-z0-9._+-]{0,62}[a-z0-9])?$/;
|
|
38
51
|
const registerSchema = z.object({
|
|
39
52
|
preferredName: z.string(),
|
|
40
|
-
tld: z.enum(SUPPORTED_TLDS).default(
|
|
53
|
+
tld: z.enum(SUPPORTED_TLDS).default("xyz"),
|
|
41
54
|
registerBasename: z.boolean().default(true),
|
|
42
55
|
registerEns: z.boolean().default(false),
|
|
43
56
|
emailEnabled: z.boolean().default(true),
|
|
@@ -46,13 +59,13 @@ const registerSchema = z.object({
|
|
|
46
59
|
.trim()
|
|
47
60
|
.toLowerCase()
|
|
48
61
|
.regex(EMAIL_USERNAME_PATTERN)
|
|
49
|
-
.default(
|
|
62
|
+
.default("agent"),
|
|
50
63
|
years: z.number().int().min(1).max(10).default(1),
|
|
51
64
|
autoRenew: z.boolean().default(false),
|
|
52
|
-
premiumPlan: z.enum(SERVICE_PLAN_KEYS).default(
|
|
65
|
+
premiumPlan: z.enum(SERVICE_PLAN_KEYS).default("included"),
|
|
53
66
|
});
|
|
54
67
|
const dnsRecordSchema = z.object({
|
|
55
|
-
type: z.enum([
|
|
68
|
+
type: z.enum(["A", "AAAA", "ALIAS", "CNAME", "MX", "TXT", "NS", "SRV"]),
|
|
56
69
|
name: z.string(),
|
|
57
70
|
value: z.string(),
|
|
58
71
|
ttl: z.number().int().min(60).max(3600).default(3600),
|
|
@@ -62,46 +75,61 @@ function parseParamsFromText(text) {
|
|
|
62
75
|
const m = text.match(TLD_PATTERN);
|
|
63
76
|
const lower = text.toLowerCase();
|
|
64
77
|
const yearsMatch = lower.match(/([1-9]|10)\s*years?/);
|
|
65
|
-
const noBasename = lower.includes(
|
|
66
|
-
lower.includes(
|
|
67
|
-
lower.includes(
|
|
68
|
-
const noEns = lower.includes(
|
|
78
|
+
const noBasename = lower.includes("no basename") ||
|
|
79
|
+
lower.includes("without basename") ||
|
|
80
|
+
lower.includes("skip basename");
|
|
81
|
+
const noEns = lower.includes("no ens") ||
|
|
82
|
+
lower.includes("without ens") ||
|
|
83
|
+
lower.includes("skip ens");
|
|
69
84
|
const wantsEns = /\bens\b/.test(lower);
|
|
70
85
|
return {
|
|
71
|
-
preferredName: m?.[1]?.toLowerCase() ??
|
|
72
|
-
tld: m?.[2]?.toLowerCase() ??
|
|
86
|
+
preferredName: m?.[1]?.toLowerCase() ?? "agent",
|
|
87
|
+
tld: m?.[2]?.toLowerCase() ?? "xyz",
|
|
73
88
|
registerBasename: !noBasename,
|
|
74
89
|
registerEns: wantsEns && !noEns,
|
|
75
90
|
emailEnabled: true,
|
|
76
|
-
emailUsername: parseEmailUsername(text) ??
|
|
91
|
+
emailUsername: parseEmailUsername(text) ?? "agent",
|
|
77
92
|
years: yearsMatch ? parseInt(yearsMatch[1], 10) : 1,
|
|
78
|
-
autoRenew: lower.includes(
|
|
93
|
+
autoRenew: lower.includes("auto renew") ||
|
|
94
|
+
lower.includes("auto-renew") ||
|
|
95
|
+
lower.includes("autorenew"),
|
|
79
96
|
premiumPlan: parseRegistrationPlan(lower),
|
|
80
97
|
};
|
|
81
98
|
}
|
|
82
99
|
function requireAgentId(text) {
|
|
83
100
|
const agentId = text.match(UUID_PATTERN)?.[0];
|
|
84
101
|
if (!agentId)
|
|
85
|
-
throw new Error(
|
|
102
|
+
throw new Error("Agent ID UUID is required");
|
|
86
103
|
return agentId;
|
|
87
104
|
}
|
|
88
105
|
function parseAmountUsdc(text) {
|
|
89
106
|
const amount = text.match(AMOUNT_PATTERN)?.[1];
|
|
90
107
|
if (!amount)
|
|
91
|
-
throw new Error(
|
|
108
|
+
throw new Error("USDC amount is required");
|
|
92
109
|
return amount;
|
|
93
110
|
}
|
|
94
111
|
function parseRegistrationPlan(lower) {
|
|
95
|
-
if (lower.includes(
|
|
96
|
-
return
|
|
97
|
-
if (lower.includes(
|
|
98
|
-
return
|
|
99
|
-
|
|
112
|
+
if (lower.includes("enterprise"))
|
|
113
|
+
return "enterprise";
|
|
114
|
+
if (lower.includes("pro"))
|
|
115
|
+
return "pro";
|
|
116
|
+
if (lower.includes("starter"))
|
|
117
|
+
return "starter";
|
|
118
|
+
return "included";
|
|
100
119
|
}
|
|
101
120
|
function parsePlan(text) {
|
|
102
121
|
const lower = text.toLowerCase();
|
|
103
|
-
|
|
104
|
-
|
|
122
|
+
if (lower.includes("enterprise")) {
|
|
123
|
+
const match = lower.match(/(\d+(?:\.\d+)?)\s*(k|m)/);
|
|
124
|
+
const monthly = match
|
|
125
|
+
? Math.round(Number(match[1]) * (match[2] === "m" ? 1_000_000 : 1_000))
|
|
126
|
+
: 100_000;
|
|
127
|
+
return {
|
|
128
|
+
plan: "enterprise",
|
|
129
|
+
planSku: `enterprise-${monthly}`,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
return { plan: lower.includes("starter") ? "starter" : "pro" };
|
|
105
133
|
}
|
|
106
134
|
function parseDnsRecord(text) {
|
|
107
135
|
const lower = text.toLowerCase();
|
|
@@ -111,17 +139,16 @@ function parseDnsRecord(text) {
|
|
|
111
139
|
const ttlMatch = text.match(/\bttl[:=]\s*(\d+)/i);
|
|
112
140
|
const priorityMatch = text.match(/\bpriority[:=]\s*(\d+)/i);
|
|
113
141
|
const parsed = dnsRecordSchema.parse({
|
|
114
|
-
type: typeMatch?.[1]?.toUpperCase() ?? (lower.includes(
|
|
115
|
-
name: nameMatch?.[1] ??
|
|
116
|
-
value: valueMatch?.[1] ?? text.match(/\b(?:\d{1,3}\.){3}\d{1,3}\b/)?.[0] ??
|
|
142
|
+
type: typeMatch?.[1]?.toUpperCase() ?? (lower.includes("txt") ? "TXT" : "A"),
|
|
143
|
+
name: nameMatch?.[1] ?? "@",
|
|
144
|
+
value: valueMatch?.[1] ?? text.match(/\b(?:\d{1,3}\.){3}\d{1,3}\b/)?.[0] ?? "",
|
|
117
145
|
ttl: ttlMatch ? Number(ttlMatch[1]) : 3600,
|
|
118
146
|
priority: priorityMatch ? Number(priorityMatch[1]) : undefined,
|
|
119
147
|
});
|
|
120
148
|
return parsed;
|
|
121
149
|
}
|
|
122
150
|
function parseEmailUsername(text) {
|
|
123
|
-
const explicit = text.match(/\b(?:email\s+username|primary\s+email|username|alias)[:=]?\s*([a-z0-9._+-]{1,64})/i)?.[1] ??
|
|
124
|
-
text.match(EMAIL_PATTERN)?.[0]?.split('@')[0];
|
|
151
|
+
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];
|
|
125
152
|
const username = explicit?.trim().toLowerCase();
|
|
126
153
|
return username && EMAIL_USERNAME_PATTERN.test(username) ? username : null;
|
|
127
154
|
}
|
|
@@ -129,18 +156,20 @@ function parseEmailRequest(text) {
|
|
|
129
156
|
const fromAddress = text.match(/\bfrom[:=]\s*([A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,})/i)?.[1];
|
|
130
157
|
const explicitTo = text.match(/\bto[:=]\s*([A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,})/i)?.[1];
|
|
131
158
|
const emails = text.match(EMAIL_GLOBAL_PATTERN) ?? [];
|
|
132
|
-
const to = explicitTo ??
|
|
159
|
+
const to = explicitTo ??
|
|
160
|
+
emails.find((email) => email.toLowerCase() !== fromAddress?.toLowerCase());
|
|
133
161
|
if (!to)
|
|
134
|
-
throw new Error(
|
|
135
|
-
const subject = text.match(/\bsubject[:=]\s*([^|]+)/i)?.[1]?.trim() ??
|
|
162
|
+
throw new Error("Recipient email address is required");
|
|
163
|
+
const subject = text.match(/\bsubject[:=]\s*([^|]+)/i)?.[1]?.trim() ??
|
|
164
|
+
"AgentDomain message";
|
|
136
165
|
const body = text.match(/\b(?:text|body|message)[:=]\s*([\s\S]+)/i)?.[1]?.trim() ??
|
|
137
|
-
text.replace(to,
|
|
138
|
-
return { to, fromAddress, subject, text: body ||
|
|
166
|
+
text.replace(to, "").trim();
|
|
167
|
+
return { to, fromAddress, subject, text: body || "Hello from AgentDomain." };
|
|
139
168
|
}
|
|
140
169
|
export const quoteRegistrationAction = {
|
|
141
|
-
name:
|
|
142
|
-
description:
|
|
143
|
-
similes: [
|
|
170
|
+
name: "QUOTE_AGENT_REGISTRATION",
|
|
171
|
+
description: "Quote an AgentDomain registration before paying.",
|
|
172
|
+
similes: ["PRICE_DOMAIN", "REGISTRATION_QUOTE", "QUOTE_IDENTITY"],
|
|
144
173
|
examples: [],
|
|
145
174
|
validate: async () => true,
|
|
146
175
|
handler: async (runtime, message) => {
|
|
@@ -154,51 +183,58 @@ export const quoteRegistrationAction = {
|
|
|
154
183
|
},
|
|
155
184
|
};
|
|
156
185
|
export const registerIdentityAction = {
|
|
157
|
-
name:
|
|
186
|
+
name: "REGISTER_IDENTITY",
|
|
158
187
|
description: 'Register a complete agent identity bundle on AgentDomain. Domain, DNS, email setup, SSL certification, AgentID NFT orchestration, and platform fee are included by default. Users can say "no basename" to skip Basename, "with ENS" to add ENS, and "email username support" to customize the primary inbox.',
|
|
159
|
-
similes: [
|
|
188
|
+
similes: ["CLAIM_DOMAIN", "CREATE_IDENTITY", "GET_DOMAIN"],
|
|
160
189
|
examples: [
|
|
161
190
|
[
|
|
162
|
-
{ user: 'user1', content: { text: 'Register me as helpful-bot.ai email username support' } },
|
|
163
191
|
{
|
|
164
|
-
user:
|
|
192
|
+
user: "user1",
|
|
193
|
+
content: {
|
|
194
|
+
text: "Register me as helpful-bot.ai email username support",
|
|
195
|
+
},
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
user: "agent",
|
|
165
199
|
content: {
|
|
166
200
|
text: "I'll register helpful-bot.ai with included email and SSL infrastructure now.",
|
|
167
|
-
action:
|
|
201
|
+
action: "REGISTER_IDENTITY",
|
|
168
202
|
},
|
|
169
203
|
},
|
|
170
204
|
],
|
|
171
205
|
],
|
|
172
|
-
validate: async (runtime, _message) => Boolean(runtime.getSetting(
|
|
206
|
+
validate: async (runtime, _message) => Boolean(runtime.getSetting("AGENT_PRIVATE_KEY")),
|
|
173
207
|
handler: async (runtime, message) => {
|
|
174
208
|
const params = parseParamsFromText(message.content.text);
|
|
175
209
|
const validated = registerSchema.parse(params);
|
|
176
|
-
const { ad, account, walletClient, chain } = getClients(runtime, {
|
|
210
|
+
const { ad, account, walletClient, chain } = getClients(runtime, {
|
|
211
|
+
requireWallet: true,
|
|
212
|
+
});
|
|
177
213
|
if (!account || !walletClient)
|
|
178
|
-
throw new Error(
|
|
214
|
+
throw new Error("AGENT_PRIVATE_KEY not set");
|
|
179
215
|
const result = await ad.register({
|
|
180
216
|
...validated,
|
|
181
217
|
emailEnabled: true,
|
|
182
218
|
wallet: account.address,
|
|
183
219
|
});
|
|
184
|
-
let autoRenewMsg =
|
|
220
|
+
let autoRenewMsg = "";
|
|
185
221
|
if (validated.autoRenew) {
|
|
186
|
-
const vaultAddress = runtime.getSetting(
|
|
222
|
+
const vaultAddress = runtime.getSetting("RENEWAL_VAULT_ADDRESS");
|
|
187
223
|
if (vaultAddress) {
|
|
188
224
|
try {
|
|
189
225
|
const txHash = await walletClient.writeContract({
|
|
190
226
|
address: vaultAddress,
|
|
191
227
|
abi: [
|
|
192
228
|
{
|
|
193
|
-
type:
|
|
194
|
-
name:
|
|
229
|
+
type: "function",
|
|
230
|
+
name: "setAutoRenew",
|
|
195
231
|
inputs: [
|
|
196
|
-
{ name:
|
|
197
|
-
{ name:
|
|
232
|
+
{ name: "tokenId", type: "uint256" },
|
|
233
|
+
{ name: "enabled", type: "bool" },
|
|
198
234
|
],
|
|
199
235
|
},
|
|
200
236
|
],
|
|
201
|
-
functionName:
|
|
237
|
+
functionName: "setAutoRenew",
|
|
202
238
|
args: [BigInt(result.nftTokenId), true],
|
|
203
239
|
chain,
|
|
204
240
|
account,
|
|
@@ -210,19 +246,20 @@ export const registerIdentityAction = {
|
|
|
210
246
|
}
|
|
211
247
|
}
|
|
212
248
|
else {
|
|
213
|
-
autoRenewMsg =
|
|
249
|
+
autoRenewMsg =
|
|
250
|
+
" (Requires RENEWAL_VAULT_ADDRESS env var to enable auto-renew on-chain).";
|
|
214
251
|
}
|
|
215
252
|
}
|
|
216
253
|
return {
|
|
217
|
-
text: `Registered ${result.domain}${result.basename ? ` and ${result.basename}` :
|
|
254
|
+
text: `Registered ${result.domain}${result.basename ? ` and ${result.basename}` : ""}. Token #${result.nftTokenId}.${autoRenewMsg}`,
|
|
218
255
|
data: result,
|
|
219
256
|
};
|
|
220
257
|
},
|
|
221
258
|
};
|
|
222
259
|
export const searchAgentsAction = {
|
|
223
|
-
name:
|
|
224
|
-
description:
|
|
225
|
-
similes: [
|
|
260
|
+
name: "SEARCH_AGENTS",
|
|
261
|
+
description: "Search the public AgentDomain registry by name, capability, or framework.",
|
|
262
|
+
similes: ["FIND_AGENT", "DISCOVER_AGENT"],
|
|
226
263
|
examples: [],
|
|
227
264
|
validate: async () => true,
|
|
228
265
|
handler: async (runtime, message) => {
|
|
@@ -236,104 +273,169 @@ export const searchAgentsAction = {
|
|
|
236
273
|
},
|
|
237
274
|
};
|
|
238
275
|
export const listEmailAction = {
|
|
239
|
-
name:
|
|
240
|
-
description:
|
|
241
|
-
similes: [
|
|
276
|
+
name: "LIST_AGENT_EMAIL",
|
|
277
|
+
description: "List text-only email messages and extracted verification codes for an AgentDomain identity.",
|
|
278
|
+
similes: ["CHECK_EMAIL", "READ_INBOX"],
|
|
242
279
|
examples: [],
|
|
243
|
-
validate: async (runtime) => Boolean(runtime.getSetting(
|
|
280
|
+
validate: async (runtime) => Boolean(runtime.getSetting("AGENT_PRIVATE_KEY")),
|
|
244
281
|
handler: async (runtime, message) => {
|
|
245
282
|
const { ad } = getClients(runtime);
|
|
246
283
|
const agentId = message.content.text.match(/[0-9a-f-]{36}/i)?.[0];
|
|
247
284
|
if (!agentId)
|
|
248
|
-
throw new Error(
|
|
285
|
+
throw new Error("Agent ID UUID is required to list email");
|
|
249
286
|
const result = await ad.listEmail(agentId, { limit: 20 });
|
|
250
287
|
return { text: `Found ${result.messages.length} messages.`, data: result };
|
|
251
288
|
},
|
|
252
289
|
};
|
|
253
290
|
export const sendEmailAction = {
|
|
254
|
-
name:
|
|
255
|
-
description:
|
|
256
|
-
similes: [
|
|
291
|
+
name: "SEND_AGENT_EMAIL",
|
|
292
|
+
description: "Send text-only email from an AgentDomain primary address or active alias.",
|
|
293
|
+
similes: ["SEND_EMAIL", "EMAIL_FROM_AGENT"],
|
|
257
294
|
examples: [],
|
|
258
|
-
validate: async (runtime) => Boolean(runtime.getSetting(
|
|
295
|
+
validate: async (runtime) => Boolean(runtime.getSetting("AGENT_PRIVATE_KEY") ||
|
|
296
|
+
runtime.getSetting("AGENTDOMAIN_API_KEY")),
|
|
259
297
|
handler: async (runtime, message) => {
|
|
260
298
|
const { ad } = getClients(runtime);
|
|
261
299
|
const agentId = requireAgentId(message.content.text);
|
|
262
300
|
const payload = parseEmailRequest(message.content.text);
|
|
263
301
|
const result = await ad.sendEmail(agentId, payload);
|
|
264
|
-
return { text: `Email
|
|
302
|
+
return { text: `Email queued: ${result.id}.`, data: result };
|
|
303
|
+
},
|
|
304
|
+
};
|
|
305
|
+
export const emailUsageAction = {
|
|
306
|
+
name: "GET_AGENT_EMAIL_USAGE",
|
|
307
|
+
description: "Get combined monthly sent and received email usage.",
|
|
308
|
+
similes: ["EMAIL_USAGE", "EMAIL_QUOTA"],
|
|
309
|
+
examples: [],
|
|
310
|
+
validate: async (runtime) => Boolean(runtime.getSetting("AGENT_PRIVATE_KEY") ||
|
|
311
|
+
runtime.getSetting("AGENTDOMAIN_API_KEY")),
|
|
312
|
+
handler: async (runtime, message) => {
|
|
313
|
+
const { ad } = getClients(runtime);
|
|
314
|
+
const result = await ad.getEmailUsage(requireAgentId(message.content.text));
|
|
315
|
+
return {
|
|
316
|
+
text: `Used ${result.used} of ${result.limit} emails; ${result.remaining} remain.`,
|
|
317
|
+
data: result,
|
|
318
|
+
};
|
|
319
|
+
},
|
|
320
|
+
};
|
|
321
|
+
export const configureEmailWebhookAction = {
|
|
322
|
+
name: "CONFIGURE_EMAIL_WEBHOOK",
|
|
323
|
+
description: "Configure a signed inbound email webhook. Include an HTTPS URL in the request.",
|
|
324
|
+
similes: ["SET_EMAIL_WEBHOOK"],
|
|
325
|
+
examples: [],
|
|
326
|
+
validate: async (runtime) => Boolean(runtime.getSetting("AGENT_PRIVATE_KEY") ||
|
|
327
|
+
runtime.getSetting("AGENTDOMAIN_API_KEY")),
|
|
328
|
+
handler: async (runtime, message) => {
|
|
329
|
+
const { ad } = getClients(runtime);
|
|
330
|
+
const agentId = requireAgentId(message.content.text);
|
|
331
|
+
const url = message.content.text.match(/https:\/\/[^\s]+/)?.[0];
|
|
332
|
+
if (!url)
|
|
333
|
+
throw new Error("HTTPS webhook URL is required");
|
|
334
|
+
const result = await ad.setEmailWebhook(agentId, {
|
|
335
|
+
url,
|
|
336
|
+
payloadMode: /inline/i.test(message.content.text)
|
|
337
|
+
? "inline_text"
|
|
338
|
+
: "metadata",
|
|
339
|
+
enabled: true,
|
|
340
|
+
});
|
|
341
|
+
return { text: "Inbound email webhook configured.", data: result };
|
|
342
|
+
},
|
|
343
|
+
};
|
|
344
|
+
export const sendEmailBatchAction = {
|
|
345
|
+
name: "SEND_AGENT_EMAIL_BATCH",
|
|
346
|
+
description: "Queue up to 100 emails supplied as a JSON messages array.",
|
|
347
|
+
similes: ["BATCH_EMAIL"],
|
|
348
|
+
examples: [],
|
|
349
|
+
validate: async (runtime) => Boolean(runtime.getSetting("AGENT_PRIVATE_KEY") ||
|
|
350
|
+
runtime.getSetting("AGENTDOMAIN_API_KEY")),
|
|
351
|
+
handler: async (runtime, message) => {
|
|
352
|
+
const { ad } = getClients(runtime);
|
|
353
|
+
const agentId = requireAgentId(message.content.text);
|
|
354
|
+
const json = message.content.text.slice(message.content.text.indexOf("{"));
|
|
355
|
+
const parsed = JSON.parse(json);
|
|
356
|
+
const result = await ad.sendEmailBatch(agentId, {
|
|
357
|
+
messages: parsed.messages,
|
|
358
|
+
});
|
|
359
|
+
return { text: `Queued ${result.jobs.length} email jobs.`, data: result };
|
|
265
360
|
},
|
|
266
361
|
};
|
|
267
362
|
export const updatePrimaryEmailAction = {
|
|
268
|
-
name:
|
|
269
|
-
description:
|
|
270
|
-
similes: [
|
|
363
|
+
name: "UPDATE_PRIMARY_EMAIL",
|
|
364
|
+
description: "Change an AgentDomain primary email username. The old primary address stops receiving new mail.",
|
|
365
|
+
similes: ["CHANGE_PRIMARY_EMAIL", "RENAME_EMAIL"],
|
|
271
366
|
examples: [],
|
|
272
|
-
validate: async (runtime) => Boolean(runtime.getSetting(
|
|
367
|
+
validate: async (runtime) => Boolean(runtime.getSetting("AGENT_PRIVATE_KEY") ||
|
|
368
|
+
runtime.getSetting("AGENTDOMAIN_API_KEY")),
|
|
273
369
|
handler: async (runtime, message) => {
|
|
274
370
|
const { ad } = getClients(runtime);
|
|
275
371
|
const agentId = requireAgentId(message.content.text);
|
|
276
372
|
const username = parseEmailUsername(message.content.text);
|
|
277
373
|
if (!username)
|
|
278
|
-
throw new Error(
|
|
374
|
+
throw new Error("New email username is required");
|
|
279
375
|
const result = await ad.updatePrimaryEmail(agentId, username);
|
|
280
376
|
return { text: result.message, data: result };
|
|
281
377
|
},
|
|
282
378
|
};
|
|
283
379
|
export const createEmailAliasAction = {
|
|
284
|
-
name:
|
|
285
|
-
description:
|
|
286
|
-
similes: [
|
|
380
|
+
name: "CREATE_EMAIL_ALIAS",
|
|
381
|
+
description: "Create a receive-and-send email alias for an AgentDomain identity. Requires available paid-plan alias capacity.",
|
|
382
|
+
similes: ["ADD_EMAIL_ALIAS", "CREATE_ALIAS"],
|
|
287
383
|
examples: [],
|
|
288
|
-
validate: async (runtime) => Boolean(runtime.getSetting(
|
|
384
|
+
validate: async (runtime) => Boolean(runtime.getSetting("AGENT_PRIVATE_KEY") ||
|
|
385
|
+
runtime.getSetting("AGENTDOMAIN_API_KEY")),
|
|
289
386
|
handler: async (runtime, message) => {
|
|
290
387
|
const { ad } = getClients(runtime);
|
|
291
388
|
const agentId = requireAgentId(message.content.text);
|
|
292
389
|
const username = parseEmailUsername(message.content.text);
|
|
293
390
|
if (!username)
|
|
294
|
-
throw new Error(
|
|
391
|
+
throw new Error("Alias username is required");
|
|
295
392
|
const result = await ad.createEmailAlias(agentId, username);
|
|
296
|
-
return {
|
|
393
|
+
return {
|
|
394
|
+
text: `Created email alias ${result.address.emailAddress}.`,
|
|
395
|
+
data: result,
|
|
396
|
+
};
|
|
297
397
|
},
|
|
298
398
|
};
|
|
299
399
|
export const deleteEmailAliasAction = {
|
|
300
|
-
name:
|
|
301
|
-
description:
|
|
302
|
-
similes: [
|
|
400
|
+
name: "DELETE_EMAIL_ALIAS",
|
|
401
|
+
description: "Delete an active AgentDomain email alias.",
|
|
402
|
+
similes: ["REMOVE_EMAIL_ALIAS", "DELETE_ALIAS"],
|
|
303
403
|
examples: [],
|
|
304
|
-
validate: async (runtime) => Boolean(runtime.getSetting(
|
|
404
|
+
validate: async (runtime) => Boolean(runtime.getSetting("AGENT_PRIVATE_KEY") ||
|
|
405
|
+
runtime.getSetting("AGENTDOMAIN_API_KEY")),
|
|
305
406
|
handler: async (runtime, message) => {
|
|
306
407
|
const { ad } = getClients(runtime);
|
|
307
408
|
const agentId = requireAgentId(message.content.text);
|
|
308
409
|
const emailAddress = message.content.text.match(EMAIL_PATTERN)?.[0];
|
|
309
410
|
if (!emailAddress)
|
|
310
|
-
throw new Error(
|
|
411
|
+
throw new Error("Full alias email address is required");
|
|
311
412
|
const result = await ad.deleteEmailAlias(agentId, emailAddress);
|
|
312
413
|
return { text: `Deleted email alias ${emailAddress}.`, data: result };
|
|
313
414
|
},
|
|
314
415
|
};
|
|
315
416
|
export const renewalStatusAction = {
|
|
316
|
-
name:
|
|
317
|
-
description:
|
|
318
|
-
similes: [
|
|
417
|
+
name: "GET_RENEWAL_STATUS",
|
|
418
|
+
description: "Get RenewalVault balance, shortfall, renewal amount, and auto-renew state.",
|
|
419
|
+
similes: ["RENEWAL_STATUS", "CHECK_RENEWAL", "VAULT_STATUS"],
|
|
319
420
|
examples: [],
|
|
320
|
-
validate: async (runtime) => Boolean(runtime.getSetting(
|
|
421
|
+
validate: async (runtime) => Boolean(runtime.getSetting("AGENT_PRIVATE_KEY") ||
|
|
422
|
+
runtime.getSetting("AGENTDOMAIN_API_KEY")),
|
|
321
423
|
handler: async (runtime, message) => {
|
|
322
424
|
const { ad } = getClients(runtime);
|
|
323
425
|
const agentId = requireAgentId(message.content.text);
|
|
324
426
|
const status = await ad.getRenewalStatus(agentId);
|
|
325
427
|
return {
|
|
326
|
-
text: `Renewal for ${status.domain}: next $${status.nextRenewalAmountUsdc}, balance $${status.vaultBalanceUsdc}, shortfall $${status.shortfallUsdc}, auto-renew ${status.autoRenewEnabled ?
|
|
428
|
+
text: `Renewal for ${status.domain}: next $${status.nextRenewalAmountUsdc}, balance $${status.vaultBalanceUsdc}, shortfall $${status.shortfallUsdc}, auto-renew ${status.autoRenewEnabled ? "enabled" : "off"}.`,
|
|
327
429
|
data: status,
|
|
328
430
|
};
|
|
329
431
|
},
|
|
330
432
|
};
|
|
331
433
|
export const fundRenewalAction = {
|
|
332
|
-
name:
|
|
333
|
-
description:
|
|
334
|
-
similes: [
|
|
434
|
+
name: "FUND_RENEWAL_VAULT",
|
|
435
|
+
description: "Deposit USDC into an AgentID renewal vault.",
|
|
436
|
+
similes: ["DEPOSIT_RENEWAL", "FUND_VAULT"],
|
|
335
437
|
examples: [],
|
|
336
|
-
validate: async (runtime) => Boolean(runtime.getSetting(
|
|
438
|
+
validate: async (runtime) => Boolean(runtime.getSetting("AGENT_PRIVATE_KEY")),
|
|
337
439
|
handler: async (runtime, message) => {
|
|
338
440
|
const { ad } = getClients(runtime, { requireWallet: true });
|
|
339
441
|
const agentId = requireAgentId(message.content.text);
|
|
@@ -346,31 +448,35 @@ export const fundRenewalAction = {
|
|
|
346
448
|
},
|
|
347
449
|
};
|
|
348
450
|
export const enableAutoRenewAction = {
|
|
349
|
-
name:
|
|
350
|
-
description:
|
|
351
|
-
similes: [
|
|
451
|
+
name: "ENABLE_AUTO_RENEW",
|
|
452
|
+
description: "Enable on-chain RenewalVault auto-renew for an AgentDomain identity.",
|
|
453
|
+
similes: ["AUTO_RENEW", "ENABLE_RENEWAL"],
|
|
352
454
|
examples: [],
|
|
353
|
-
validate: async (runtime) => Boolean(runtime.getSetting(
|
|
455
|
+
validate: async (runtime) => Boolean(runtime.getSetting("AGENT_PRIVATE_KEY") &&
|
|
456
|
+
runtime.getSetting("RENEWAL_VAULT_ADDRESS")),
|
|
354
457
|
handler: async (runtime, message) => {
|
|
355
458
|
const { ad } = getClients(runtime, { requireWallet: true });
|
|
356
459
|
const agentId = requireAgentId(message.content.text);
|
|
357
460
|
const result = await ad.setAutoRenew(agentId, true, {
|
|
358
|
-
renewalVaultAddress: runtime.getSetting(
|
|
461
|
+
renewalVaultAddress: runtime.getSetting("RENEWAL_VAULT_ADDRESS"),
|
|
359
462
|
});
|
|
360
|
-
return {
|
|
463
|
+
return {
|
|
464
|
+
text: `Auto-renew enabled for token #${result.tokenId}.`,
|
|
465
|
+
data: result,
|
|
466
|
+
};
|
|
361
467
|
},
|
|
362
468
|
};
|
|
363
469
|
export const reconfigureSslAction = {
|
|
364
|
-
name:
|
|
365
|
-
description:
|
|
366
|
-
similes: [
|
|
470
|
+
name: "RECONFIGURE_SSL",
|
|
471
|
+
description: "Rebuild the Cloudflare SaaS SSL hostname and sync Spaceship DNS validation records for an AgentDomain identity.",
|
|
472
|
+
similes: ["FIX_SSL", "REPAIR_SSL", "SYNC_SSL"],
|
|
367
473
|
examples: [],
|
|
368
|
-
validate: async (runtime) => Boolean(runtime.getSetting(
|
|
474
|
+
validate: async (runtime) => Boolean(runtime.getSetting("AGENT_PRIVATE_KEY")),
|
|
369
475
|
handler: async (runtime, message) => {
|
|
370
476
|
const { ad } = getClients(runtime);
|
|
371
477
|
const agentId = message.content.text.match(/[0-9a-f-]{36}/i)?.[0];
|
|
372
478
|
if (!agentId)
|
|
373
|
-
throw new Error(
|
|
479
|
+
throw new Error("Agent ID UUID is required to reconfigure SSL");
|
|
374
480
|
const result = await ad.reconfigureSsl(agentId);
|
|
375
481
|
return {
|
|
376
482
|
text: `SSL reconfigured for ${result.domain}. Status: ${result.sslStatus}.`,
|
|
@@ -379,11 +485,12 @@ export const reconfigureSslAction = {
|
|
|
379
485
|
},
|
|
380
486
|
};
|
|
381
487
|
export const listDnsAction = {
|
|
382
|
-
name:
|
|
383
|
-
description:
|
|
384
|
-
similes: [
|
|
488
|
+
name: "LIST_DNS_RECORDS",
|
|
489
|
+
description: "List DNS records for an AgentDomain identity.",
|
|
490
|
+
similes: ["DNS_RECORDS", "LIST_DNS"],
|
|
385
491
|
examples: [],
|
|
386
|
-
validate: async (runtime) => Boolean(runtime.getSetting(
|
|
492
|
+
validate: async (runtime) => Boolean(runtime.getSetting("AGENT_PRIVATE_KEY") ||
|
|
493
|
+
runtime.getSetting("AGENTDOMAIN_API_KEY")),
|
|
387
494
|
handler: async (runtime, message) => {
|
|
388
495
|
const { ad } = getClients(runtime);
|
|
389
496
|
const agentId = requireAgentId(message.content.text);
|
|
@@ -392,98 +499,113 @@ export const listDnsAction = {
|
|
|
392
499
|
},
|
|
393
500
|
};
|
|
394
501
|
export const createDnsAction = {
|
|
395
|
-
name:
|
|
396
|
-
description:
|
|
397
|
-
similes: [
|
|
502
|
+
name: "CREATE_DNS_RECORD",
|
|
503
|
+
description: "Create a user-managed DNS record. Use text like: agentId type A name @ value 1.2.3.4.",
|
|
504
|
+
similes: ["ADD_DNS", "CREATE_DNS"],
|
|
398
505
|
examples: [],
|
|
399
|
-
validate: async (runtime) => Boolean(runtime.getSetting(
|
|
506
|
+
validate: async (runtime) => Boolean(runtime.getSetting("AGENT_PRIVATE_KEY") ||
|
|
507
|
+
runtime.getSetting("AGENTDOMAIN_API_KEY")),
|
|
400
508
|
handler: async (runtime, message) => {
|
|
401
509
|
const { ad } = getClients(runtime);
|
|
402
510
|
const agentId = requireAgentId(message.content.text);
|
|
403
511
|
const record = parseDnsRecord(message.content.text);
|
|
404
512
|
const result = await ad.createDnsRecord(agentId, record);
|
|
405
|
-
return {
|
|
513
|
+
return {
|
|
514
|
+
text: `Created ${result.type} DNS record ${result.name}.`,
|
|
515
|
+
data: result,
|
|
516
|
+
};
|
|
406
517
|
},
|
|
407
518
|
};
|
|
408
519
|
export const updateDnsAction = {
|
|
409
|
-
name:
|
|
410
|
-
description:
|
|
411
|
-
similes: [
|
|
520
|
+
name: "UPDATE_DNS_RECORD",
|
|
521
|
+
description: "Update a user-managed DNS record. Include agent UUID and record UUID.",
|
|
522
|
+
similes: ["EDIT_DNS", "UPDATE_DNS"],
|
|
412
523
|
examples: [],
|
|
413
|
-
validate: async (runtime) => Boolean(runtime.getSetting(
|
|
524
|
+
validate: async (runtime) => Boolean(runtime.getSetting("AGENT_PRIVATE_KEY") ||
|
|
525
|
+
runtime.getSetting("AGENTDOMAIN_API_KEY")),
|
|
414
526
|
handler: async (runtime, message) => {
|
|
415
527
|
const { ad } = getClients(runtime);
|
|
416
|
-
const ids = message.content.text.match(new RegExp(UUID_PATTERN.source,
|
|
528
|
+
const ids = message.content.text.match(new RegExp(UUID_PATTERN.source, "gi")) ?? [];
|
|
417
529
|
const agentId = ids[0];
|
|
418
530
|
const recordId = ids[1];
|
|
419
531
|
if (!agentId || !recordId)
|
|
420
|
-
throw new Error(
|
|
532
|
+
throw new Error("Agent ID and record ID UUIDs are required");
|
|
421
533
|
const record = parseDnsRecord(message.content.text);
|
|
422
534
|
const result = await ad.updateDnsRecord(agentId, recordId, record);
|
|
423
|
-
return {
|
|
535
|
+
return {
|
|
536
|
+
text: `Updated ${result.type} DNS record ${result.name}.`,
|
|
537
|
+
data: result,
|
|
538
|
+
};
|
|
424
539
|
},
|
|
425
540
|
};
|
|
426
541
|
export const deleteDnsAction = {
|
|
427
|
-
name:
|
|
428
|
-
description:
|
|
429
|
-
similes: [
|
|
542
|
+
name: "DELETE_DNS_RECORD",
|
|
543
|
+
description: "Delete a user-managed DNS record. Include agent UUID and record UUID.",
|
|
544
|
+
similes: ["REMOVE_DNS", "DELETE_DNS"],
|
|
430
545
|
examples: [],
|
|
431
|
-
validate: async (runtime) => Boolean(runtime.getSetting(
|
|
546
|
+
validate: async (runtime) => Boolean(runtime.getSetting("AGENT_PRIVATE_KEY") ||
|
|
547
|
+
runtime.getSetting("AGENTDOMAIN_API_KEY")),
|
|
432
548
|
handler: async (runtime, message) => {
|
|
433
549
|
const { ad } = getClients(runtime);
|
|
434
|
-
const ids = message.content.text.match(new RegExp(UUID_PATTERN.source,
|
|
550
|
+
const ids = message.content.text.match(new RegExp(UUID_PATTERN.source, "gi")) ?? [];
|
|
435
551
|
const agentId = ids[0];
|
|
436
552
|
const recordId = ids[1];
|
|
437
553
|
if (!agentId || !recordId)
|
|
438
|
-
throw new Error(
|
|
554
|
+
throw new Error("Agent ID and record ID UUIDs are required");
|
|
439
555
|
const result = await ad.deleteDnsRecord(agentId, recordId);
|
|
440
556
|
return { text: `Deleted DNS record ${recordId}.`, data: result };
|
|
441
557
|
},
|
|
442
558
|
};
|
|
443
559
|
export const servicePlanStatusAction = {
|
|
444
|
-
name:
|
|
445
|
-
description:
|
|
446
|
-
similes: [
|
|
560
|
+
name: "GET_SERVICE_PLAN",
|
|
561
|
+
description: "Get an agent Premium Plan, limits, current period, and billing state.",
|
|
562
|
+
similes: ["PLAN_STATUS", "CHECK_PLAN"],
|
|
447
563
|
examples: [],
|
|
448
|
-
validate: async (runtime) => Boolean(runtime.getSetting(
|
|
564
|
+
validate: async (runtime) => Boolean(runtime.getSetting("AGENT_PRIVATE_KEY") ||
|
|
565
|
+
runtime.getSetting("AGENTDOMAIN_API_KEY")),
|
|
449
566
|
handler: async (runtime, message) => {
|
|
450
567
|
const { ad } = getClients(runtime);
|
|
451
568
|
const agentId = requireAgentId(message.content.text);
|
|
452
569
|
const result = await ad.getServicePlan(agentId);
|
|
453
570
|
return {
|
|
454
|
-
text: `${result.domain} is on ${result.entitlement.plan}. Email limit ${result.entitlement.limits.
|
|
571
|
+
text: `${result.domain} is on ${result.entitlement.plan}. Email limit ${result.entitlement.limits.monthlyEmails}/month combined, DNS limit ${result.entitlement.limits.dnsRecords}, registry hidden ${result.registryVisibility.hidden}.`,
|
|
455
572
|
data: result,
|
|
456
573
|
};
|
|
457
574
|
},
|
|
458
575
|
};
|
|
459
576
|
export const setRegistryVisibilityAction = {
|
|
460
|
-
name:
|
|
461
|
-
description:
|
|
462
|
-
similes: [
|
|
577
|
+
name: "SET_REGISTRY_VISIBILITY",
|
|
578
|
+
description: "Hide or show an agent in the public AgentDomain registry. Hiding requires an active paid Premium Plan.",
|
|
579
|
+
similes: [
|
|
580
|
+
"HIDE_AGENT_REGISTRY",
|
|
581
|
+
"SHOW_AGENT_REGISTRY",
|
|
582
|
+
"REGISTRY_VISIBILITY",
|
|
583
|
+
],
|
|
463
584
|
examples: [],
|
|
464
|
-
validate: async (runtime) => Boolean(runtime.getSetting(
|
|
585
|
+
validate: async (runtime) => Boolean(runtime.getSetting("AGENT_PRIVATE_KEY") ||
|
|
586
|
+
runtime.getSetting("AGENTDOMAIN_API_KEY")),
|
|
465
587
|
handler: async (runtime, message) => {
|
|
466
588
|
const { ad } = getClients(runtime);
|
|
467
589
|
const agentId = requireAgentId(message.content.text);
|
|
468
590
|
const text = message.content.text.toLowerCase();
|
|
469
|
-
const wantsPublic = text.includes(
|
|
470
|
-
text.includes(
|
|
471
|
-
text.includes(
|
|
472
|
-
text.includes(
|
|
473
|
-
const registryHidden = !wantsPublic && (text.includes(
|
|
591
|
+
const wantsPublic = text.includes("unhide") ||
|
|
592
|
+
text.includes("show") ||
|
|
593
|
+
text.includes("visible") ||
|
|
594
|
+
text.includes("public");
|
|
595
|
+
const registryHidden = !wantsPublic && (text.includes("hide") || text.includes("private"));
|
|
474
596
|
const result = await ad.setRegistryVisibility(agentId, registryHidden);
|
|
475
597
|
return {
|
|
476
|
-
text: `${result.domain} is now ${result.registryVisibility.hidden ?
|
|
598
|
+
text: `${result.domain} is now ${result.registryVisibility.hidden ? "hidden from" : "visible in"} the public registry.`,
|
|
477
599
|
data: result,
|
|
478
600
|
};
|
|
479
601
|
},
|
|
480
602
|
};
|
|
481
603
|
export const purchaseServicePlanAction = {
|
|
482
|
-
name:
|
|
483
|
-
description:
|
|
484
|
-
similes: [
|
|
604
|
+
name: "PURCHASE_SERVICE_PLAN",
|
|
605
|
+
description: "Upgrade an agent to AgentDomain Starter, Pro, or Enterprise using x402 USDC.",
|
|
606
|
+
similes: ["BUY_PLAN", "UPGRADE_PLAN"],
|
|
485
607
|
examples: [],
|
|
486
|
-
validate: async (runtime) => Boolean(runtime.getSetting(
|
|
608
|
+
validate: async (runtime) => Boolean(runtime.getSetting("AGENT_PRIVATE_KEY")),
|
|
487
609
|
handler: async (runtime, message) => {
|
|
488
610
|
const { ad } = getClients(runtime, { requireWallet: true });
|
|
489
611
|
const agentId = requireAgentId(message.content.text);
|
|
@@ -499,13 +621,16 @@ export const purchaseServicePlanAction = {
|
|
|
499
621
|
},
|
|
500
622
|
};
|
|
501
623
|
export const agentDomainPlugin = {
|
|
502
|
-
name:
|
|
503
|
-
description:
|
|
624
|
+
name: "agentdomain",
|
|
625
|
+
description: "Identity infrastructure for AI agents on Base (domain + Basename + DNS + email + SSL).",
|
|
504
626
|
actions: [
|
|
505
627
|
quoteRegistrationAction,
|
|
506
628
|
registerIdentityAction,
|
|
507
629
|
searchAgentsAction,
|
|
508
630
|
sendEmailAction,
|
|
631
|
+
sendEmailBatchAction,
|
|
632
|
+
emailUsageAction,
|
|
633
|
+
configureEmailWebhookAction,
|
|
509
634
|
listEmailAction,
|
|
510
635
|
updatePrimaryEmailAction,
|
|
511
636
|
createEmailAliasAction,
|
package/package.json
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentdomain/eliza-plugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "ElizaOS plugin for AgentDomain - give your Eliza agent a complete identity stack",
|
|
5
|
-
"license": "
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
|
+
"repository": "https://github.com/0xmdrakib/AgentDomain.git",
|
|
7
|
+
"homepage": "https://agentdomain.app/docs",
|
|
8
|
+
"bugs": "https://github.com/0xmdrakib/AgentDomain/issues",
|
|
6
9
|
"type": "module",
|
|
7
10
|
"main": "./dist/index.js",
|
|
8
11
|
"types": "./dist/index.d.ts",
|
|
@@ -23,8 +26,8 @@
|
|
|
23
26
|
"dependencies": {
|
|
24
27
|
"viem": "^2.55.2",
|
|
25
28
|
"zod": "^3.24.1",
|
|
26
|
-
"@agentdomain/sdk": "^0.
|
|
27
|
-
"@agentdomain/shared": "^0.
|
|
29
|
+
"@agentdomain/sdk": "^0.4.0",
|
|
30
|
+
"@agentdomain/shared": "^0.4.0"
|
|
28
31
|
},
|
|
29
32
|
"peerDependencies": {
|
|
30
33
|
"@elizaos/core": "^1.0.0"
|