a2a-xmtp 1.2.4 → 1.3.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/README.md +8 -7
- package/dist/coordination/message-orchestrator.d.ts +55 -0
- package/dist/coordination/message-orchestrator.d.ts.map +1 -0
- package/dist/coordination/message-orchestrator.js +142 -0
- package/dist/coordination/message-orchestrator.js.map +1 -0
- package/dist/coordination/policy-engine.d.ts +34 -0
- package/dist/coordination/policy-engine.d.ts.map +1 -0
- package/dist/coordination/policy-engine.js +92 -0
- package/dist/coordination/policy-engine.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +163 -0
- package/dist/index.js.map +1 -0
- package/dist/tools/xmtp-agents.d.ts +19 -0
- package/dist/tools/xmtp-agents.d.ts.map +1 -0
- package/dist/tools/xmtp-agents.js +27 -0
- package/dist/tools/xmtp-agents.js.map +1 -0
- package/dist/tools/xmtp-group.d.ts +95 -0
- package/dist/tools/xmtp-group.d.ts.map +1 -0
- package/dist/tools/xmtp-group.js +134 -0
- package/dist/tools/xmtp-group.js.map +1 -0
- package/dist/tools/xmtp-inbox.d.ts +22 -0
- package/dist/tools/xmtp-inbox.d.ts.map +1 -0
- package/dist/tools/xmtp-inbox.js +36 -0
- package/dist/tools/xmtp-inbox.js.map +1 -0
- package/dist/tools/xmtp-send.d.ts +28 -0
- package/dist/tools/xmtp-send.d.ts.map +1 -0
- package/dist/tools/xmtp-send.js +63 -0
- package/dist/tools/xmtp-send.js.map +1 -0
- package/dist/transport/identity-registry.d.ts +30 -0
- package/dist/transport/identity-registry.d.ts.map +1 -0
- package/dist/transport/identity-registry.js +117 -0
- package/dist/transport/identity-registry.js.map +1 -0
- package/dist/transport/xmtp-bridge.d.ts +55 -0
- package/dist/transport/xmtp-bridge.d.ts.map +1 -0
- package/dist/transport/xmtp-bridge.js +265 -0
- package/dist/transport/xmtp-bridge.js.map +1 -0
- package/dist/types.d.ts +100 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +51 -0
- package/dist/types.js.map +1 -0
- package/package.json +27 -16
- package/src/identity-registry.ts +0 -134
- package/src/index.ts +0 -327
- package/src/policy-engine.ts +0 -121
- package/src/tools/xmtp-agents.ts +0 -38
- package/src/tools/xmtp-group.ts +0 -153
- package/src/tools/xmtp-inbox.ts +0 -47
- package/src/tools/xmtp-send.ts +0 -77
- package/src/types.ts +0 -155
- package/src/xmtp-bridge.ts +0 -283
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
// ============================================================
|
|
2
|
+
// Module 2: XMTP Bridge Service
|
|
3
|
+
// 每个 Agent 对应一个 XMTP Client,消息 stream + 收件箱缓存
|
|
4
|
+
// ============================================================
|
|
5
|
+
import { Agent, createUser, createSigner } from "@xmtp/agent-sdk";
|
|
6
|
+
import { createA2APayload } from "../types.js";
|
|
7
|
+
/** IdentifierKind.Ethereum = 0 (const enum, 不能在 isolatedModules 下直接访问) */
|
|
8
|
+
const IDENTIFIER_KIND_ETHEREUM = 0;
|
|
9
|
+
export class XmtpBridge {
|
|
10
|
+
agentId;
|
|
11
|
+
walletConfig;
|
|
12
|
+
policyEngine;
|
|
13
|
+
registry;
|
|
14
|
+
dbPath;
|
|
15
|
+
agent = null;
|
|
16
|
+
running = false;
|
|
17
|
+
syncTimer = null;
|
|
18
|
+
/** 收件箱缓存 */
|
|
19
|
+
inboxBuffer = [];
|
|
20
|
+
maxInboxBuffer = 100;
|
|
21
|
+
/** 消息回调(由 plugin 入口设置,用于触发 subagent 处理) */
|
|
22
|
+
onMessage;
|
|
23
|
+
constructor(agentId, walletConfig, policyEngine, registry, dbPath) {
|
|
24
|
+
this.agentId = agentId;
|
|
25
|
+
this.walletConfig = walletConfig;
|
|
26
|
+
this.policyEngine = policyEngine;
|
|
27
|
+
this.registry = registry;
|
|
28
|
+
this.dbPath = dbPath;
|
|
29
|
+
}
|
|
30
|
+
async start() {
|
|
31
|
+
if (this.running)
|
|
32
|
+
return;
|
|
33
|
+
// Reconstruct full user from stored key — createUser() accepts an existing private key
|
|
34
|
+
const user = createUser(this.walletConfig.privateKey);
|
|
35
|
+
const signer = createSigner(user);
|
|
36
|
+
this.agent = await Agent.create(signer, {
|
|
37
|
+
env: this.walletConfig.env,
|
|
38
|
+
dbPath: `${this.dbPath}/${this.agentId}`,
|
|
39
|
+
});
|
|
40
|
+
await this.registry.updateInboxId(this.agentId, this.agent.address);
|
|
41
|
+
this.agent.on("text", async (ctx) => {
|
|
42
|
+
await this.handleIncoming(ctx, "text");
|
|
43
|
+
});
|
|
44
|
+
this.agent.on("markdown", async (ctx) => {
|
|
45
|
+
await this.handleIncoming(ctx, "markdown");
|
|
46
|
+
});
|
|
47
|
+
await this.agent.start();
|
|
48
|
+
this.running = true;
|
|
49
|
+
// 定期同步会话列表,发现被外部添加到的新群聊(每 30 秒)
|
|
50
|
+
this.syncTimer = setInterval(async () => {
|
|
51
|
+
try {
|
|
52
|
+
await this.agent?.client.conversations.sync();
|
|
53
|
+
}
|
|
54
|
+
catch { /* 同步失败不影响正常运行 */ }
|
|
55
|
+
}, 30_000);
|
|
56
|
+
}
|
|
57
|
+
async stop() {
|
|
58
|
+
if (!this.running || !this.agent)
|
|
59
|
+
return;
|
|
60
|
+
if (this.syncTimer) {
|
|
61
|
+
clearInterval(this.syncTimer);
|
|
62
|
+
this.syncTimer = null;
|
|
63
|
+
}
|
|
64
|
+
await this.agent.stop();
|
|
65
|
+
this.running = false;
|
|
66
|
+
}
|
|
67
|
+
async sendMessage(toAddress, content, opts) {
|
|
68
|
+
if (!this.agent)
|
|
69
|
+
throw new Error(`Bridge for ${this.agentId} not started`);
|
|
70
|
+
let conversation;
|
|
71
|
+
if (opts?.conversationId) {
|
|
72
|
+
conversation = await this.agent.client.conversations.getConversationById(opts.conversationId);
|
|
73
|
+
if (!conversation)
|
|
74
|
+
throw new Error(`Conversation ${opts.conversationId} not found`);
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
conversation = await this.agent.createDmWithAddress(toAddress);
|
|
78
|
+
}
|
|
79
|
+
const messageId = opts?.contentType === "markdown"
|
|
80
|
+
? await conversation.sendMarkdown(content)
|
|
81
|
+
: await conversation.sendText(content);
|
|
82
|
+
this.policyEngine.recordTurn(conversation.id);
|
|
83
|
+
return { conversationId: conversation.id, messageId: String(messageId) };
|
|
84
|
+
}
|
|
85
|
+
async getInbox(opts) {
|
|
86
|
+
const limit = opts?.limit ?? 10;
|
|
87
|
+
let messages = [...this.inboxBuffer];
|
|
88
|
+
if (opts?.from) {
|
|
89
|
+
const f = opts.from.toLowerCase();
|
|
90
|
+
messages = messages.filter((m) => m.from.agentId === opts.from || m.from.xmtpAddress.toLowerCase() === f);
|
|
91
|
+
}
|
|
92
|
+
return messages.slice(0, limit);
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* 获取指定会话的最近消息(供 coordination 层查询)
|
|
96
|
+
*/
|
|
97
|
+
getRecentMessages(conversationId, limit) {
|
|
98
|
+
return this.inboxBuffer
|
|
99
|
+
.filter((m) => m.conversationId === conversationId)
|
|
100
|
+
.slice(0, limit);
|
|
101
|
+
}
|
|
102
|
+
async createGroup(memberAddresses, name) {
|
|
103
|
+
if (!this.agent)
|
|
104
|
+
throw new Error(`Bridge for ${this.agentId} not started`);
|
|
105
|
+
const opts = name ? { groupName: name } : undefined;
|
|
106
|
+
const group = await this.agent.createGroupWithAddresses(memberAddresses, opts);
|
|
107
|
+
if (name) {
|
|
108
|
+
try {
|
|
109
|
+
await group.updateName(name);
|
|
110
|
+
}
|
|
111
|
+
catch { /* 部分 SDK 版本 createGroupWithAddresses 不支持 opts */ }
|
|
112
|
+
}
|
|
113
|
+
return { conversationId: group.id, name: group.name ?? name ?? "" };
|
|
114
|
+
}
|
|
115
|
+
async listGroups() {
|
|
116
|
+
if (!this.agent)
|
|
117
|
+
throw new Error(`Bridge for ${this.agentId} not started`);
|
|
118
|
+
const conversations = await this.agent.client.conversations.list();
|
|
119
|
+
const groups = [];
|
|
120
|
+
for (const conv of conversations) {
|
|
121
|
+
const meta = await conv.metadata();
|
|
122
|
+
if (meta.conversationType !== 1)
|
|
123
|
+
continue; // 1 = Group, 0 = Dm
|
|
124
|
+
const members = await conv.members();
|
|
125
|
+
groups.push({
|
|
126
|
+
conversationId: conv.id,
|
|
127
|
+
name: conv.name ?? "",
|
|
128
|
+
memberAddresses: members.map((m) => m.accountAddresses?.[0]?.toLowerCase() ?? m.inboxId),
|
|
129
|
+
createdAt: conv.createdAt.toISOString(),
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
return groups;
|
|
133
|
+
}
|
|
134
|
+
async getGroupMembers(conversationId) {
|
|
135
|
+
if (!this.agent)
|
|
136
|
+
throw new Error(`Bridge for ${this.agentId} not started`);
|
|
137
|
+
const conv = await this.agent.client.conversations.getConversationById(conversationId);
|
|
138
|
+
if (!conv)
|
|
139
|
+
throw new Error(`Conversation ${conversationId} not found`);
|
|
140
|
+
const members = await conv.members();
|
|
141
|
+
return members.map((m) => m.accountAddresses?.[0]?.toLowerCase() ?? m.inboxId);
|
|
142
|
+
}
|
|
143
|
+
async addGroupMembers(conversationId, addresses) {
|
|
144
|
+
if (!this.agent)
|
|
145
|
+
throw new Error(`Bridge for ${this.agentId} not started`);
|
|
146
|
+
const conv = await this.agent.client.conversations.getConversationById(conversationId);
|
|
147
|
+
if (!conv)
|
|
148
|
+
throw new Error(`Conversation ${conversationId} not found`);
|
|
149
|
+
const identifiers = addresses.map((addr) => ({
|
|
150
|
+
identifier: addr,
|
|
151
|
+
identifierKind: IDENTIFIER_KIND_ETHEREUM,
|
|
152
|
+
}));
|
|
153
|
+
await conv.addMembersByIdentifiers(identifiers);
|
|
154
|
+
}
|
|
155
|
+
async removeGroupMembers(conversationId, addresses) {
|
|
156
|
+
if (!this.agent)
|
|
157
|
+
throw new Error(`Bridge for ${this.agentId} not started`);
|
|
158
|
+
const conv = await this.agent.client.conversations.getConversationById(conversationId);
|
|
159
|
+
if (!conv)
|
|
160
|
+
throw new Error(`Conversation ${conversationId} not found`);
|
|
161
|
+
const identifiers = addresses.map((addr) => ({
|
|
162
|
+
identifier: addr,
|
|
163
|
+
identifierKind: IDENTIFIER_KIND_ETHEREUM,
|
|
164
|
+
}));
|
|
165
|
+
await conv.removeMembersByIdentifiers(identifiers);
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* 检查群聊中在 afterTimestamp 之后是否有新消息(排除自身和指定 sender)
|
|
169
|
+
* 用于防止多 agent 同时回复同一条消息
|
|
170
|
+
*/
|
|
171
|
+
async hasNewGroupReplies(conversationId, afterTimestamp, excludeAddresses) {
|
|
172
|
+
if (!this.agent)
|
|
173
|
+
return false;
|
|
174
|
+
try {
|
|
175
|
+
const conv = await this.agent.client.conversations.getConversationById(conversationId);
|
|
176
|
+
if (!conv)
|
|
177
|
+
return false;
|
|
178
|
+
await conv.sync();
|
|
179
|
+
const messages = await conv.messages({ limit: BigInt(10) });
|
|
180
|
+
const cutoffMs = new Date(afterTimestamp).getTime();
|
|
181
|
+
const excluded = new Set(excludeAddresses.map((a) => a.toLowerCase()));
|
|
182
|
+
return messages.some((m) => {
|
|
183
|
+
const sentMs = Number(BigInt(m.sentAtNs) / 1000000n);
|
|
184
|
+
const sender = (m.senderInboxId ?? m.senderAddress ?? "").toLowerCase();
|
|
185
|
+
return sentMs > cutoffMs && !excluded.has(sender);
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
catch {
|
|
189
|
+
return false;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
async canMessage(address) {
|
|
193
|
+
if (!this.agent)
|
|
194
|
+
return false;
|
|
195
|
+
const result = await this.agent.client.canMessage([
|
|
196
|
+
{ identifier: address, identifierKind: IDENTIFIER_KIND_ETHEREUM },
|
|
197
|
+
]);
|
|
198
|
+
return result.get(address.toLowerCase()) ?? false;
|
|
199
|
+
}
|
|
200
|
+
async handleIncoming(ctx, contentType) {
|
|
201
|
+
const senderAddress = await ctx.getSenderAddress();
|
|
202
|
+
if (senderAddress.toLowerCase() === this.address.toLowerCase())
|
|
203
|
+
return;
|
|
204
|
+
const senderAgentId = await this.registry.resolveAgentId(senderAddress);
|
|
205
|
+
const policyResult = this.policyEngine.checkIncoming({
|
|
206
|
+
from: senderAgentId || senderAddress,
|
|
207
|
+
to: this.agentId,
|
|
208
|
+
conversationId: ctx.conversation.id,
|
|
209
|
+
});
|
|
210
|
+
if (!policyResult.allowed)
|
|
211
|
+
return;
|
|
212
|
+
const convState = this.policyEngine.getConversationState(ctx.conversation.id);
|
|
213
|
+
const turn = convState?.turn ?? 0;
|
|
214
|
+
const depth = convState?.depth ?? 0;
|
|
215
|
+
this.policyEngine.recordTurn(ctx.conversation.id, depth + 1);
|
|
216
|
+
// 群聊时获取参与者列表
|
|
217
|
+
let participants = [];
|
|
218
|
+
const isGroup = ctx.conversation.isGroup ?? false;
|
|
219
|
+
if (isGroup) {
|
|
220
|
+
try {
|
|
221
|
+
const members = await ctx.conversation.members();
|
|
222
|
+
participants = members.map((m) => m.accountAddresses?.[0]?.toLowerCase() ?? m.inboxId);
|
|
223
|
+
}
|
|
224
|
+
catch { /* 获取成员失败时保持空数组 */ }
|
|
225
|
+
}
|
|
226
|
+
const payload = createA2APayload({
|
|
227
|
+
fromAgentId: senderAgentId,
|
|
228
|
+
fromAddress: senderAddress,
|
|
229
|
+
conversationId: ctx.conversation.id,
|
|
230
|
+
isGroup,
|
|
231
|
+
participants,
|
|
232
|
+
messageId: ctx.message.id ?? crypto.randomUUID(),
|
|
233
|
+
content: String(ctx.message.content),
|
|
234
|
+
contentType,
|
|
235
|
+
turn: turn + 1,
|
|
236
|
+
depth: depth + 1,
|
|
237
|
+
});
|
|
238
|
+
// 缓存到 inbox
|
|
239
|
+
this.inboxBuffer.unshift({
|
|
240
|
+
id: payload.message.id,
|
|
241
|
+
from: { agentId: senderAgentId, xmtpAddress: senderAddress },
|
|
242
|
+
conversationId: ctx.conversation.id,
|
|
243
|
+
isGroup,
|
|
244
|
+
content: String(ctx.message.content),
|
|
245
|
+
contentType,
|
|
246
|
+
timestamp: payload.timestamp,
|
|
247
|
+
});
|
|
248
|
+
if (this.inboxBuffer.length > this.maxInboxBuffer)
|
|
249
|
+
this.inboxBuffer.pop();
|
|
250
|
+
// 通知 plugin 层(传递结构化 payload,由调用方决定如何处理)
|
|
251
|
+
if (this.onMessage) {
|
|
252
|
+
this.onMessage(this.agentId, payload);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
get address() {
|
|
256
|
+
return this.agent?.address ?? this.walletConfig.address;
|
|
257
|
+
}
|
|
258
|
+
get isConnected() {
|
|
259
|
+
return this.running;
|
|
260
|
+
}
|
|
261
|
+
get env() {
|
|
262
|
+
return this.walletConfig.env;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
//# sourceMappingURL=xmtp-bridge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"xmtp-bridge.js","sourceRoot":"","sources":["../../src/transport/xmtp-bridge.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/** Agent 的 XMTP 钱包配置 */
|
|
2
|
+
export interface XmtpWalletConfig {
|
|
3
|
+
privateKey: string;
|
|
4
|
+
address: string;
|
|
5
|
+
xmtpInboxId: string;
|
|
6
|
+
env: XmtpEnv;
|
|
7
|
+
}
|
|
8
|
+
export type XmtpEnv = "dev" | "production";
|
|
9
|
+
/** 注入 Agent session 的消息格式 */
|
|
10
|
+
export interface A2AInjectPayload {
|
|
11
|
+
type: "a2a-xmtp";
|
|
12
|
+
from: {
|
|
13
|
+
agentId: string | null;
|
|
14
|
+
xmtpAddress: string;
|
|
15
|
+
displayName?: string;
|
|
16
|
+
};
|
|
17
|
+
conversation: {
|
|
18
|
+
id: string;
|
|
19
|
+
isGroup: boolean;
|
|
20
|
+
participants: string[];
|
|
21
|
+
};
|
|
22
|
+
message: {
|
|
23
|
+
id: string;
|
|
24
|
+
content: string;
|
|
25
|
+
contentType: A2AContentType;
|
|
26
|
+
turn: number;
|
|
27
|
+
depth: number;
|
|
28
|
+
replyTo?: string;
|
|
29
|
+
};
|
|
30
|
+
timestamp: string;
|
|
31
|
+
}
|
|
32
|
+
export type A2AContentType = "text" | "markdown" | "transaction" | "action";
|
|
33
|
+
/** 防循环策略配置 */
|
|
34
|
+
export interface ConversationPolicy {
|
|
35
|
+
maxTurns: number;
|
|
36
|
+
maxDepth: number;
|
|
37
|
+
minIntervalMs: number;
|
|
38
|
+
ttlMinutes: number;
|
|
39
|
+
consentMode: ConsentMode;
|
|
40
|
+
}
|
|
41
|
+
export type ConsentMode = "auto-allow-local" | "explicit-only";
|
|
42
|
+
export type ConsentState = "allow" | "deny" | "unknown";
|
|
43
|
+
/** 插件运行时配置(从 openclaw.json entries.a2a-xmtp.config 解析) */
|
|
44
|
+
export interface PluginConfig {
|
|
45
|
+
xmtp: {
|
|
46
|
+
env: XmtpEnv;
|
|
47
|
+
dbPath: string;
|
|
48
|
+
};
|
|
49
|
+
policy: ConversationPolicy;
|
|
50
|
+
walletKey?: string;
|
|
51
|
+
}
|
|
52
|
+
/** 会话状态(Policy Engine 内部使用) */
|
|
53
|
+
export interface ConversationState {
|
|
54
|
+
turn: number;
|
|
55
|
+
depth: number;
|
|
56
|
+
lastSendTime: number;
|
|
57
|
+
createdAt: number;
|
|
58
|
+
}
|
|
59
|
+
/** 收件箱消息 */
|
|
60
|
+
export interface InboxMessage {
|
|
61
|
+
id: string;
|
|
62
|
+
from: {
|
|
63
|
+
agentId: string | null;
|
|
64
|
+
xmtpAddress: string;
|
|
65
|
+
};
|
|
66
|
+
conversationId: string;
|
|
67
|
+
isGroup: boolean;
|
|
68
|
+
content: string;
|
|
69
|
+
contentType: A2AContentType;
|
|
70
|
+
timestamp: string;
|
|
71
|
+
}
|
|
72
|
+
/** 群聊信息 */
|
|
73
|
+
export interface GroupInfo {
|
|
74
|
+
conversationId: string;
|
|
75
|
+
name: string;
|
|
76
|
+
memberAddresses: string[];
|
|
77
|
+
createdAt: string;
|
|
78
|
+
}
|
|
79
|
+
/** 默认策略配置 */
|
|
80
|
+
export declare const DEFAULT_POLICY: ConversationPolicy;
|
|
81
|
+
/** 默认插件配置 */
|
|
82
|
+
export declare const DEFAULT_PLUGIN_CONFIG: PluginConfig;
|
|
83
|
+
/** 格式化 A2A 消息(注入 session 时的文本表示) */
|
|
84
|
+
export declare function formatA2AMessage(payload: A2AInjectPayload): string;
|
|
85
|
+
/** 创建 A2AInjectPayload */
|
|
86
|
+
export declare function createA2APayload(params: {
|
|
87
|
+
fromAgentId: string | null;
|
|
88
|
+
fromAddress: string;
|
|
89
|
+
conversationId: string;
|
|
90
|
+
isGroup: boolean;
|
|
91
|
+
participants: string[];
|
|
92
|
+
messageId: string;
|
|
93
|
+
content: string;
|
|
94
|
+
contentType: A2AContentType;
|
|
95
|
+
turn: number;
|
|
96
|
+
depth: number;
|
|
97
|
+
replyTo?: string;
|
|
98
|
+
displayName?: string;
|
|
99
|
+
}): A2AInjectPayload;
|
|
100
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// ============================================================
|
|
2
|
+
// Module 6: 类型定义 & 消息协议适配
|
|
3
|
+
// ============================================================
|
|
4
|
+
/** 默认策略配置 */
|
|
5
|
+
export const DEFAULT_POLICY = {
|
|
6
|
+
maxTurns: 10,
|
|
7
|
+
maxDepth: 5,
|
|
8
|
+
minIntervalMs: 5000,
|
|
9
|
+
ttlMinutes: 60,
|
|
10
|
+
consentMode: "auto-allow-local",
|
|
11
|
+
};
|
|
12
|
+
/** 默认插件配置 */
|
|
13
|
+
export const DEFAULT_PLUGIN_CONFIG = {
|
|
14
|
+
xmtp: {
|
|
15
|
+
env: "dev",
|
|
16
|
+
dbPath: "./xmtp-data",
|
|
17
|
+
},
|
|
18
|
+
policy: DEFAULT_POLICY,
|
|
19
|
+
};
|
|
20
|
+
/** 格式化 A2A 消息(注入 session 时的文本表示) */
|
|
21
|
+
export function formatA2AMessage(payload) {
|
|
22
|
+
const sender = payload.from.agentId || payload.from.xmtpAddress;
|
|
23
|
+
const prefix = payload.conversation.isGroup ? "[A2A Group]" : "[A2A]";
|
|
24
|
+
return `${prefix} from ${sender} (turn ${payload.message.turn}): ${payload.message.content}`;
|
|
25
|
+
}
|
|
26
|
+
/** 创建 A2AInjectPayload */
|
|
27
|
+
export function createA2APayload(params) {
|
|
28
|
+
return {
|
|
29
|
+
type: "a2a-xmtp",
|
|
30
|
+
from: {
|
|
31
|
+
agentId: params.fromAgentId,
|
|
32
|
+
xmtpAddress: params.fromAddress,
|
|
33
|
+
displayName: params.displayName,
|
|
34
|
+
},
|
|
35
|
+
conversation: {
|
|
36
|
+
id: params.conversationId,
|
|
37
|
+
isGroup: params.isGroup,
|
|
38
|
+
participants: params.participants,
|
|
39
|
+
},
|
|
40
|
+
message: {
|
|
41
|
+
id: params.messageId,
|
|
42
|
+
content: params.content,
|
|
43
|
+
contentType: params.contentType,
|
|
44
|
+
turn: params.turn,
|
|
45
|
+
depth: params.depth,
|
|
46
|
+
replyTo: params.replyTo,
|
|
47
|
+
},
|
|
48
|
+
timestamp: new Date().toISOString(),
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,0BAA0B;AAC1B,+DAA+D;AA0F/D,aAAa;AACb,MAAM,CAAC,MAAM,cAAc,GAAuB;IAChD,QAAQ,EAAE,EAAE;IACZ,QAAQ,EAAE,CAAC;IACX,aAAa,EAAE,IAAI;IACnB,UAAU,EAAE,EAAE;IACd,WAAW,EAAE,kBAAkB;CAChC,CAAC;AAEF,aAAa;AACb,MAAM,CAAC,MAAM,qBAAqB,GAAiB;IACjD,IAAI,EAAE;QACJ,GAAG,EAAE,KAAK;QACV,MAAM,EAAE,aAAa;KACtB;IACD,MAAM,EAAE,cAAc;CACvB,CAAC;AAEF,oCAAoC;AACpC,MAAM,UAAU,gBAAgB,CAAC,OAAyB;IACxD,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC;IAChE,MAAM,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC;IACtE,OAAO,GAAG,MAAM,SAAS,MAAM,UAAU,OAAO,CAAC,OAAO,CAAC,IAAI,MAAM,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;AAC/F,CAAC;AAED,0BAA0B;AAC1B,MAAM,UAAU,gBAAgB,CAAC,MAahC;IACC,OAAO;QACL,IAAI,EAAE,UAAU;QAChB,IAAI,EAAE;YACJ,OAAO,EAAE,MAAM,CAAC,WAAW;YAC3B,WAAW,EAAE,MAAM,CAAC,WAAW;YAC/B,WAAW,EAAE,MAAM,CAAC,WAAW;SAChC;QACD,YAAY,EAAE;YACZ,EAAE,EAAE,MAAM,CAAC,cAAc;YACzB,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,YAAY,EAAE,MAAM,CAAC,YAAY;SAClC;QACD,OAAO,EAAE;YACP,EAAE,EAAE,MAAM,CAAC,SAAS;YACpB,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,WAAW,EAAE,MAAM,CAAC,WAAW;YAC/B,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,OAAO,EAAE,MAAM,CAAC,OAAO;SACxB;QACD,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACpC,CAAC;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,21 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "a2a-xmtp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"main": "
|
|
6
|
-
"types": "
|
|
7
|
-
"dependencies": {
|
|
8
|
-
"@xmtp/agent-sdk": "^2.3.0",
|
|
9
|
-
"@sinclair/typebox": "^0.34.0"
|
|
10
|
-
},
|
|
11
|
-
"peerDependencies": {
|
|
12
|
-
"openclaw": "*"
|
|
13
|
-
},
|
|
14
|
-
"openclaw": {
|
|
15
|
-
"extensions": [
|
|
16
|
-
"./src/index.ts"
|
|
17
|
-
]
|
|
18
|
-
},
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
19
7
|
"description": "Decentralized Agent-to-Agent E2EE messaging for OpenClaw via XMTP",
|
|
20
8
|
"keywords": [
|
|
21
9
|
"openclaw",
|
|
@@ -27,8 +15,31 @@
|
|
|
27
15
|
"web3"
|
|
28
16
|
],
|
|
29
17
|
"license": "MIT",
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsc",
|
|
20
|
+
"test": "vitest run",
|
|
21
|
+
"test:watch": "vitest",
|
|
22
|
+
"lint": "tsc --noEmit"
|
|
23
|
+
},
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"@xmtp/agent-sdk": "^2.3.0",
|
|
26
|
+
"@sinclair/typebox": "^0.34.0"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"typescript": "^5.7.0",
|
|
30
|
+
"vitest": "^3.0.0",
|
|
31
|
+
"@types/node": "^22.0.0"
|
|
32
|
+
},
|
|
33
|
+
"peerDependencies": {
|
|
34
|
+
"openclaw": "*"
|
|
35
|
+
},
|
|
36
|
+
"openclaw": {
|
|
37
|
+
"extensions": [
|
|
38
|
+
"./dist/index.js"
|
|
39
|
+
]
|
|
40
|
+
},
|
|
30
41
|
"files": [
|
|
31
|
-
"
|
|
42
|
+
"dist/",
|
|
32
43
|
"openclaw.plugin.json",
|
|
33
44
|
"package.json",
|
|
34
45
|
"README.md"
|
package/src/identity-registry.ts
DELETED
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
// ============================================================
|
|
2
|
-
// Module 3: Identity Registry
|
|
3
|
-
// agentId ↔ XMTP wallet address 双向映射,wallet key 生成/加载
|
|
4
|
-
// 使用文件系统持久化(stateDir)
|
|
5
|
-
// ============================================================
|
|
6
|
-
|
|
7
|
-
import { createUser, createSigner } from "@xmtp/agent-sdk";
|
|
8
|
-
import { privateKeyToAccount } from "viem/accounts";
|
|
9
|
-
import { readFileSync, writeFileSync, mkdirSync, existsSync } from "node:fs";
|
|
10
|
-
import { join } from "node:path";
|
|
11
|
-
import type { XmtpWalletConfig, XmtpEnv } from "./types.js";
|
|
12
|
-
|
|
13
|
-
export class IdentityRegistry {
|
|
14
|
-
private agentToConfig = new Map<string, XmtpWalletConfig>();
|
|
15
|
-
private addressToAgent = new Map<string, string>();
|
|
16
|
-
private storePath: string;
|
|
17
|
-
|
|
18
|
-
constructor(
|
|
19
|
-
stateDir: string,
|
|
20
|
-
private env: XmtpEnv = "dev",
|
|
21
|
-
) {
|
|
22
|
-
this.storePath = join(stateDir, "identities");
|
|
23
|
-
mkdirSync(this.storePath, { recursive: true });
|
|
24
|
-
this.loadFromDisk();
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* 为 Agent 初始化 XMTP wallet。
|
|
29
|
-
* 如果已有配置则加载,否则生成新的 wallet。
|
|
30
|
-
*/
|
|
31
|
-
async initAgent(agentId: string, existingKey?: string): Promise<XmtpWalletConfig> {
|
|
32
|
-
const cached = this.agentToConfig.get(agentId);
|
|
33
|
-
if (cached) return cached;
|
|
34
|
-
|
|
35
|
-
// 尝试从磁盘加载
|
|
36
|
-
const filePath = join(this.storePath, `${agentId}.json`);
|
|
37
|
-
if (existsSync(filePath)) {
|
|
38
|
-
const config: XmtpWalletConfig = JSON.parse(readFileSync(filePath, "utf-8"));
|
|
39
|
-
this.cacheMapping(agentId, config);
|
|
40
|
-
return config;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// 生成新 wallet 或使用提供的 key
|
|
44
|
-
let privateKey: string;
|
|
45
|
-
let address: string;
|
|
46
|
-
|
|
47
|
-
if (existingKey) {
|
|
48
|
-
privateKey = existingKey;
|
|
49
|
-
const account = privateKeyToAccount(existingKey as `0x${string}`);
|
|
50
|
-
address = account.address;
|
|
51
|
-
} else {
|
|
52
|
-
const user = createUser();
|
|
53
|
-
privateKey = user.key; // createUser() returns { key, account, wallet }
|
|
54
|
-
address = user.account.address;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const config: XmtpWalletConfig = {
|
|
58
|
-
privateKey,
|
|
59
|
-
address,
|
|
60
|
-
xmtpInboxId: "",
|
|
61
|
-
env: this.env,
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
// 持久化到磁盘
|
|
65
|
-
writeFileSync(filePath, JSON.stringify(config, null, 2));
|
|
66
|
-
this.cacheMapping(agentId, config);
|
|
67
|
-
|
|
68
|
-
return config;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/** 更新 inboxId */
|
|
72
|
-
async updateInboxId(agentId: string, inboxId: string): Promise<void> {
|
|
73
|
-
const config = this.agentToConfig.get(agentId);
|
|
74
|
-
if (!config) return;
|
|
75
|
-
config.xmtpInboxId = inboxId;
|
|
76
|
-
const filePath = join(this.storePath, `${agentId}.json`);
|
|
77
|
-
writeFileSync(filePath, JSON.stringify(config, null, 2));
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
getAddress(agentId: string): string | undefined {
|
|
81
|
-
return this.agentToConfig.get(agentId)?.address;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
getConfig(agentId: string): XmtpWalletConfig | undefined {
|
|
85
|
-
return this.agentToConfig.get(agentId);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
getAgentId(address: string): string | undefined {
|
|
89
|
-
return this.addressToAgent.get(address.toLowerCase());
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
async resolveAgentId(address: string): Promise<string | null> {
|
|
93
|
-
return this.addressToAgent.get(address.toLowerCase()) ?? null;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
listAgents(): Array<{ agentId: string; address: string; env: XmtpEnv }> {
|
|
97
|
-
return Array.from(this.agentToConfig.entries()).map(([id, config]) => ({
|
|
98
|
-
agentId: id,
|
|
99
|
-
address: config.address,
|
|
100
|
-
env: config.env,
|
|
101
|
-
}));
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
has(agentId: string): boolean {
|
|
105
|
-
return this.agentToConfig.has(agentId);
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
registerExternal(address: string, agentId: string): void {
|
|
109
|
-
this.addressToAgent.set(address.toLowerCase(), agentId);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
private cacheMapping(agentId: string, config: XmtpWalletConfig): void {
|
|
113
|
-
this.agentToConfig.set(agentId, config);
|
|
114
|
-
this.addressToAgent.set(config.address.toLowerCase(), agentId);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/** 从磁盘加载所有已有 identity */
|
|
118
|
-
private loadFromDisk(): void {
|
|
119
|
-
if (!existsSync(this.storePath)) return;
|
|
120
|
-
const { readdirSync } = require("node:fs") as typeof import("node:fs");
|
|
121
|
-
for (const file of readdirSync(this.storePath)) {
|
|
122
|
-
if (!file.endsWith(".json")) continue;
|
|
123
|
-
const agentId = file.replace(".json", "");
|
|
124
|
-
try {
|
|
125
|
-
const config: XmtpWalletConfig = JSON.parse(
|
|
126
|
-
readFileSync(join(this.storePath, file), "utf-8"),
|
|
127
|
-
);
|
|
128
|
-
this.cacheMapping(agentId, config);
|
|
129
|
-
} catch {
|
|
130
|
-
// skip corrupt files
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|