@hybrd/xmtp 1.4.4 → 2.0.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 +209 -319
- package/dist/index.cjs +138 -83
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +19 -1
- package/dist/index.d.ts +19 -1
- package/dist/index.js +131 -78
- package/dist/index.js.map +1 -1
- package/package.json +10 -6
- package/src/client.ts +19 -39
- package/src/index.ts +8 -5
- package/src/lib/jwt.ts +16 -23
- package/src/lib/secret.ts +33 -0
- package/src/plugin.ts +98 -39
- package/src/index.ts.old +0 -145
- package/src/lib/message-listener.test.ts.old +0 -369
- package/src/lib/message-listener.ts.old +0 -343
- package/src/localStorage.ts.old +0 -203
- package/src/plugin.filters.test.ts +0 -158
- package/src/service-client.ts.old +0 -309
- package/src/transactionMonitor.ts.old +0 -275
- package/src/types.ts.old +0 -157
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { toBytes } from "viem"
|
|
2
|
+
import { HDKey } from "viem/accounts"
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Derives a deterministic 32-byte secret from an agent wallet private key.
|
|
6
|
+
*
|
|
7
|
+
* Uses BIP-32 HD key derivation at path m/44'/60'/0'/0/41 (coin type 60 = ETH,
|
|
8
|
+
* index 41 is arbitrary but fixed — chosen to avoid collision with standard
|
|
9
|
+
* account derivation paths). The child private key is used directly as the
|
|
10
|
+
* 32-byte secret, returned as a 64-character hex string.
|
|
11
|
+
*/
|
|
12
|
+
export function deriveAgentSecret(walletKey: string): string {
|
|
13
|
+
const keyBytes = toBytes(walletKey as `0x${string}`)
|
|
14
|
+
const hdKey = HDKey.fromMasterSeed(keyBytes)
|
|
15
|
+
const child = hdKey.derive("m/44'/60'/0'/0/41")
|
|
16
|
+
if (!child.privateKey) {
|
|
17
|
+
throw new Error("Failed to derive child key from wallet key")
|
|
18
|
+
}
|
|
19
|
+
return Buffer.from(child.privateKey).toString("hex")
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Resolves the database encryption secret by deriving it from the provided wallet key.
|
|
24
|
+
*
|
|
25
|
+
* The wallet key must be passed explicitly — this function does not
|
|
26
|
+
* read from environment variables or external stores.
|
|
27
|
+
*/
|
|
28
|
+
export function resolveAgentSecret(walletKey: string): string {
|
|
29
|
+
if (!walletKey) {
|
|
30
|
+
throw new Error("walletKey is required to derive the encryption secret")
|
|
31
|
+
}
|
|
32
|
+
return deriveAgentSecret(walletKey)
|
|
33
|
+
}
|
package/src/plugin.ts
CHANGED
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
createUser
|
|
6
6
|
} from "@xmtp/agent-sdk"
|
|
7
7
|
|
|
8
|
+
import { randomUUID } from "node:crypto"
|
|
8
9
|
import type {
|
|
9
10
|
AgentMessage,
|
|
10
11
|
AgentRuntime,
|
|
@@ -17,7 +18,6 @@ import type {
|
|
|
17
18
|
XmtpMessage
|
|
18
19
|
} from "@hybrd/types"
|
|
19
20
|
import { logger } from "@hybrd/utils"
|
|
20
|
-
import { randomUUID } from "node:crypto"
|
|
21
21
|
import { createXMTPClient, getDbPath } from "./client"
|
|
22
22
|
import { ContentTypeReply, ContentTypeText, type Reply } from "./index"
|
|
23
23
|
|
|
@@ -74,30 +74,22 @@ export function XMTPPlugin(): Plugin<PluginContext> {
|
|
|
74
74
|
name: "xmtp",
|
|
75
75
|
description: "Provides XMTP messaging functionality",
|
|
76
76
|
apply: async (app, context): Promise<void> => {
|
|
77
|
-
const {
|
|
78
|
-
XMTP_WALLET_KEY,
|
|
79
|
-
XMTP_DB_ENCRYPTION_KEY,
|
|
80
|
-
XMTP_ENV = "production"
|
|
81
|
-
} = process.env
|
|
77
|
+
const { AGENT_WALLET_KEY, XMTP_ENV = "production" } = process.env
|
|
82
78
|
|
|
83
79
|
const { agent } = context
|
|
84
80
|
const pluginContext = context as PluginContext & {
|
|
85
81
|
behaviors?: BehaviorRegistry
|
|
86
82
|
}
|
|
87
83
|
|
|
88
|
-
if (!
|
|
89
|
-
throw new Error("
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
if (!XMTP_DB_ENCRYPTION_KEY) {
|
|
93
|
-
throw new Error("XMTP_DB_ENCRYPTION_KEY must be set")
|
|
84
|
+
if (!AGENT_WALLET_KEY) {
|
|
85
|
+
throw new Error("AGENT_WALLET_KEY must be set")
|
|
94
86
|
}
|
|
95
87
|
|
|
96
|
-
const user = createUser(
|
|
88
|
+
const user = createUser(AGENT_WALLET_KEY as `0x${string}`)
|
|
97
89
|
const signer = createSigner(user)
|
|
98
90
|
|
|
99
91
|
const xmtpClient = await createXMTPClient(
|
|
100
|
-
|
|
92
|
+
AGENT_WALLET_KEY as `0x${string}`
|
|
101
93
|
)
|
|
102
94
|
|
|
103
95
|
const address = user.account.address.toLowerCase()
|
|
@@ -106,12 +98,15 @@ export function XMTPPlugin(): Plugin<PluginContext> {
|
|
|
106
98
|
)
|
|
107
99
|
logger.debug(`📁 Using database path: ${agentDbPath}`)
|
|
108
100
|
|
|
109
|
-
const xmtp = await XmtpAgent.create(signer, {
|
|
101
|
+
const xmtp = (await XmtpAgent.create(signer, {
|
|
110
102
|
env: XMTP_ENV as XmtpEnv,
|
|
111
103
|
dbPath: agentDbPath
|
|
112
|
-
})
|
|
104
|
+
})) as any
|
|
105
|
+
|
|
106
|
+
const botInboxId = xmtp.client?.inboxId
|
|
107
|
+
const MAX_HISTORY = 20
|
|
113
108
|
|
|
114
|
-
xmtp.on("reaction", async ({ conversation, message }) => {
|
|
109
|
+
xmtp.on("reaction", async ({ conversation, message }: any) => {
|
|
115
110
|
try {
|
|
116
111
|
const text = message.content.content
|
|
117
112
|
const messages: AgentMessage[] = [
|
|
@@ -125,35 +120,64 @@ export function XMTPPlugin(): Plugin<PluginContext> {
|
|
|
125
120
|
const baseRuntime: AgentRuntime = {
|
|
126
121
|
conversation: conversation as unknown as XmtpConversation,
|
|
127
122
|
message: message as unknown as XmtpMessage,
|
|
128
|
-
xmtpClient
|
|
123
|
+
xmtpClient,
|
|
124
|
+
...(context.scheduler ? { scheduler: context.scheduler } : {})
|
|
129
125
|
}
|
|
130
126
|
|
|
131
127
|
const runtime = await agent.createRuntimeContext(baseRuntime)
|
|
132
128
|
|
|
133
129
|
// Execute pre-response behaviors
|
|
130
|
+
let behaviorContext: BehaviorContext | undefined
|
|
134
131
|
if (context.behaviors) {
|
|
135
|
-
|
|
132
|
+
behaviorContext = {
|
|
136
133
|
runtime,
|
|
137
134
|
client: xmtpClient as unknown as XmtpClient,
|
|
138
135
|
conversation: conversation as unknown as XmtpConversation,
|
|
139
136
|
message: message as unknown as XmtpMessage
|
|
140
137
|
}
|
|
141
138
|
await context.behaviors.executeBefore(behaviorContext)
|
|
139
|
+
|
|
140
|
+
// Check if behaviors were stopped early (e.g., due to filtering)
|
|
141
|
+
if (behaviorContext.stopped) {
|
|
142
|
+
logger.debug(
|
|
143
|
+
`🔇 [XMTP Plugin] Skipping reaction response due to behavior chain being stopped`
|
|
144
|
+
)
|
|
145
|
+
return
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Check if message was filtered out by filterMessages behavior
|
|
149
|
+
if (behaviorContext.sendOptions?.filtered) {
|
|
150
|
+
logger.debug(
|
|
151
|
+
`🔇 [XMTP Plugin] Skipping reaction response due to message being filtered`
|
|
152
|
+
)
|
|
153
|
+
return
|
|
154
|
+
}
|
|
142
155
|
}
|
|
143
156
|
|
|
144
157
|
const { text: reply } = await agent.generate(messages, { runtime })
|
|
145
158
|
|
|
146
159
|
// Execute post-response behaviors
|
|
147
|
-
let behaviorContext: BehaviorContext | undefined
|
|
148
160
|
if (context.behaviors) {
|
|
149
|
-
behaviorContext
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
161
|
+
if (behaviorContext) {
|
|
162
|
+
behaviorContext.response = reply
|
|
163
|
+
} else {
|
|
164
|
+
behaviorContext = {
|
|
165
|
+
runtime,
|
|
166
|
+
client: xmtpClient as unknown as XmtpClient,
|
|
167
|
+
conversation: conversation as unknown as XmtpConversation,
|
|
168
|
+
message: message as unknown as XmtpMessage,
|
|
169
|
+
response: reply
|
|
170
|
+
}
|
|
155
171
|
}
|
|
156
172
|
await context.behaviors.executeAfter(behaviorContext)
|
|
173
|
+
|
|
174
|
+
// Check if post behaviors were stopped early
|
|
175
|
+
if (behaviorContext.stopped) {
|
|
176
|
+
logger.debug(
|
|
177
|
+
`🔇 [XMTP Plugin] Skipping reaction response due to post-behavior chain being stopped`
|
|
178
|
+
)
|
|
179
|
+
return
|
|
180
|
+
}
|
|
157
181
|
} else {
|
|
158
182
|
// Create minimal context for send options
|
|
159
183
|
behaviorContext = {
|
|
@@ -165,14 +189,6 @@ export function XMTPPlugin(): Plugin<PluginContext> {
|
|
|
165
189
|
}
|
|
166
190
|
}
|
|
167
191
|
|
|
168
|
-
// Check if message was filtered out by filterMessages behavior
|
|
169
|
-
if (behaviorContext?.sendOptions?.filtered) {
|
|
170
|
-
logger.debug(
|
|
171
|
-
`🔇 [XMTP Plugin] Skipping reaction response due to message being filtered`
|
|
172
|
-
)
|
|
173
|
-
return
|
|
174
|
-
}
|
|
175
|
-
|
|
176
192
|
await sendResponse(
|
|
177
193
|
conversation as unknown as XmtpConversation,
|
|
178
194
|
reply,
|
|
@@ -184,7 +200,7 @@ export function XMTPPlugin(): Plugin<PluginContext> {
|
|
|
184
200
|
}
|
|
185
201
|
})
|
|
186
202
|
|
|
187
|
-
xmtp.on("reply", async ({ conversation, message }) => {
|
|
203
|
+
xmtp.on("reply", async ({ conversation, message }: any) => {
|
|
188
204
|
try {
|
|
189
205
|
// TODO - why isn't this typed better?
|
|
190
206
|
const text = message.content.content as string
|
|
@@ -199,7 +215,8 @@ export function XMTPPlugin(): Plugin<PluginContext> {
|
|
|
199
215
|
const baseRuntime: AgentRuntime = {
|
|
200
216
|
conversation: conversation as unknown as XmtpConversation,
|
|
201
217
|
message: message as unknown as XmtpMessage,
|
|
202
|
-
xmtpClient
|
|
218
|
+
xmtpClient,
|
|
219
|
+
...(context.scheduler ? { scheduler: context.scheduler } : {})
|
|
203
220
|
}
|
|
204
221
|
|
|
205
222
|
const runtime = await agent.createRuntimeContext(baseRuntime)
|
|
@@ -270,17 +287,56 @@ export function XMTPPlugin(): Plugin<PluginContext> {
|
|
|
270
287
|
}
|
|
271
288
|
})
|
|
272
289
|
|
|
273
|
-
xmtp.on("text", async ({ conversation, message }) => {
|
|
290
|
+
xmtp.on("text", async ({ conversation, message }: any) => {
|
|
274
291
|
try {
|
|
275
292
|
const text = message.content
|
|
293
|
+
|
|
294
|
+
let historyMessages: AgentMessage[] = []
|
|
295
|
+
try {
|
|
296
|
+
console.log("[xmtp] fetching conversation history...")
|
|
297
|
+
const history = await conversation.messages({
|
|
298
|
+
limit: MAX_HISTORY + 1,
|
|
299
|
+
direction: 1
|
|
300
|
+
})
|
|
301
|
+
|
|
302
|
+
console.log(
|
|
303
|
+
`[xmtp] got ${history.length} messages from conversation.messages()`
|
|
304
|
+
)
|
|
305
|
+
|
|
306
|
+
const filtered = history
|
|
307
|
+
.filter((msg: any) => msg.id !== message.id)
|
|
308
|
+
.filter(
|
|
309
|
+
(msg: any) => msg.content && typeof msg.content === "string"
|
|
310
|
+
)
|
|
311
|
+
.slice(0, MAX_HISTORY)
|
|
312
|
+
.reverse()
|
|
313
|
+
|
|
314
|
+
console.log(`[xmtp] after filter: ${filtered.length} messages`)
|
|
315
|
+
|
|
316
|
+
historyMessages = filtered.map((msg: any) => ({
|
|
317
|
+
id: msg.id,
|
|
318
|
+
role:
|
|
319
|
+
msg.senderInboxId === botInboxId
|
|
320
|
+
? ("assistant" as const)
|
|
321
|
+
: ("user" as const),
|
|
322
|
+
parts: [{ type: "text" as const, text: msg.content as string }]
|
|
323
|
+
}))
|
|
324
|
+
} catch (historyErr) {
|
|
325
|
+
console.error(`[xmtp] history error:`, historyErr)
|
|
326
|
+
}
|
|
327
|
+
|
|
276
328
|
const messages: AgentMessage[] = [
|
|
329
|
+
...historyMessages,
|
|
277
330
|
{ id: randomUUID(), role: "user", parts: [{ type: "text", text }] }
|
|
278
331
|
]
|
|
279
332
|
|
|
333
|
+
console.log(`[xmtp] sending ${messages.length} messages to agent`)
|
|
334
|
+
|
|
280
335
|
const baseRuntime: AgentRuntime = {
|
|
281
336
|
conversation: conversation as unknown as XmtpConversation,
|
|
282
337
|
message: message as unknown as XmtpMessage,
|
|
283
|
-
xmtpClient
|
|
338
|
+
xmtpClient,
|
|
339
|
+
...(context.scheduler ? { scheduler: context.scheduler } : {})
|
|
284
340
|
}
|
|
285
341
|
|
|
286
342
|
const runtime = await agent.createRuntimeContext(baseRuntime)
|
|
@@ -351,12 +407,15 @@ export function XMTPPlugin(): Plugin<PluginContext> {
|
|
|
351
407
|
}
|
|
352
408
|
})
|
|
353
409
|
|
|
410
|
+
// Store xmtpClient in context for scheduler and other components
|
|
411
|
+
;(context as any).xmtpClient = xmtpClient
|
|
412
|
+
|
|
354
413
|
// Event handlers removed due to incompatibility with current XMTP agent SDK
|
|
355
414
|
|
|
356
415
|
void xmtp
|
|
357
416
|
.start()
|
|
358
417
|
.then(() => logger.debug("✅ XMTP agent listener started"))
|
|
359
|
-
.catch((err) =>
|
|
418
|
+
.catch((err: any) =>
|
|
360
419
|
console.error("❌ XMTP agent listener failed to start:", err)
|
|
361
420
|
)
|
|
362
421
|
}
|
package/src/index.ts.old
DELETED
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
// ===================================================================
|
|
2
|
-
// XMTP Package - Main Entry Point
|
|
3
|
-
// ===================================================================
|
|
4
|
-
// This package provides a clean interface to XMTP functionality
|
|
5
|
-
// Re-exports core XMTP SDK types and utilities
|
|
6
|
-
|
|
7
|
-
// export * from "./client"
|
|
8
|
-
// export * from "./constants"
|
|
9
|
-
// export * from "./lib/message-listener"
|
|
10
|
-
// export * from "./lib/subjects"
|
|
11
|
-
// export * from "./resolver"
|
|
12
|
-
// export * from "./resolver/basename-resolver"
|
|
13
|
-
// export * from "./resolver/ens-resolver"
|
|
14
|
-
// export * from "./resolver/xmtp-resolver"
|
|
15
|
-
// export * from "./service-client"
|
|
16
|
-
// export * from "./types"
|
|
17
|
-
|
|
18
|
-
// ===================================================================
|
|
19
|
-
// XMTP Plugin for Agent Integration
|
|
20
|
-
// ===================================================================
|
|
21
|
-
export { XMTPPlugin } from "./plugin"
|
|
22
|
-
export type { Plugin, XMTPPluginContext } from "./plugin"
|
|
23
|
-
|
|
24
|
-
// ===================================================================
|
|
25
|
-
// JWT Utilities for XMTP Tools
|
|
26
|
-
// ===================================================================
|
|
27
|
-
export { generateXMTPToolsToken } from "./lib/jwt"
|
|
28
|
-
export type { XMTPToolsPayload } from "./lib/jwt"
|
|
29
|
-
export { logger } from "./lib/logger"
|
|
30
|
-
|
|
31
|
-
// ===================================================================
|
|
32
|
-
// Enhanced XMTP Client & Connection Management
|
|
33
|
-
// ===================================================================
|
|
34
|
-
// export {
|
|
35
|
-
// // Enhanced connection management
|
|
36
|
-
// XMTPConnectionManager,
|
|
37
|
-
// createXMTPConnectionManager,
|
|
38
|
-
// type XMTPConnectionConfig,
|
|
39
|
-
// type XMTPConnectionHealth
|
|
40
|
-
// } from "./client"
|
|
41
|
-
|
|
42
|
-
// ===================================================================
|
|
43
|
-
// XMTP Service Client (for external service communication)
|
|
44
|
-
// ===================================================================
|
|
45
|
-
// export {
|
|
46
|
-
// XmtpServiceClient,
|
|
47
|
-
// createXmtpServiceClient
|
|
48
|
-
// } from "./service-client"
|
|
49
|
-
|
|
50
|
-
// Service Client Types
|
|
51
|
-
// export type {
|
|
52
|
-
// GetMessageParams,
|
|
53
|
-
// GetRootMessageParams,
|
|
54
|
-
// // Function parameter types
|
|
55
|
-
// SendMessageParams,
|
|
56
|
-
// // Response types
|
|
57
|
-
// SendMessageResponse,
|
|
58
|
-
// SendReactionParams,
|
|
59
|
-
// SendReactionResponse,
|
|
60
|
-
// SendReplyParams,
|
|
61
|
-
// SendReplyResponse,
|
|
62
|
-
// SendTransactionParams,
|
|
63
|
-
// SendTransactionResponse,
|
|
64
|
-
// TransactionCall,
|
|
65
|
-
// TransactionRequest,
|
|
66
|
-
// XmtpRootMessageResponse,
|
|
67
|
-
// XmtpServiceClientConfig,
|
|
68
|
-
// XmtpServiceMessage,
|
|
69
|
-
// XmtpServiceResponse
|
|
70
|
-
// } from "./types"
|
|
71
|
-
|
|
72
|
-
// ===================================================================
|
|
73
|
-
// XMTP Core SDK Exports
|
|
74
|
-
// ===================================================================
|
|
75
|
-
export {
|
|
76
|
-
Client,
|
|
77
|
-
IdentifierKind,
|
|
78
|
-
// type Conversation,
|
|
79
|
-
type DecodedMessage,
|
|
80
|
-
type Dm,
|
|
81
|
-
// type Group,
|
|
82
|
-
type LogLevel,
|
|
83
|
-
type Signer,
|
|
84
|
-
type XmtpEnv
|
|
85
|
-
} from "@xmtp/node-sdk"
|
|
86
|
-
|
|
87
|
-
// ===================================================================
|
|
88
|
-
// XMTP Content Types
|
|
89
|
-
// ===================================================================
|
|
90
|
-
export {
|
|
91
|
-
ContentTypeTransactionReference,
|
|
92
|
-
type TransactionReference
|
|
93
|
-
} from "@xmtp/content-type-transaction-reference"
|
|
94
|
-
|
|
95
|
-
export { ContentTypeText, type TextParameters } from "@xmtp/content-type-text"
|
|
96
|
-
|
|
97
|
-
export {
|
|
98
|
-
ContentTypeReaction,
|
|
99
|
-
type Reaction
|
|
100
|
-
} from "@xmtp/content-type-reaction"
|
|
101
|
-
|
|
102
|
-
export {
|
|
103
|
-
ContentTypeReply,
|
|
104
|
-
ReplyCodec,
|
|
105
|
-
type Reply
|
|
106
|
-
} from "@xmtp/content-type-reply"
|
|
107
|
-
|
|
108
|
-
export {
|
|
109
|
-
ContentTypeGroupUpdated,
|
|
110
|
-
GroupUpdatedCodec,
|
|
111
|
-
type GroupUpdated
|
|
112
|
-
} from "@xmtp/content-type-group-updated"
|
|
113
|
-
|
|
114
|
-
export {
|
|
115
|
-
ContentTypeWalletSendCalls,
|
|
116
|
-
type WalletSendCallsParams
|
|
117
|
-
} from "@xmtp/content-type-wallet-send-calls"
|
|
118
|
-
|
|
119
|
-
// ===================================================================
|
|
120
|
-
// Local Client Utilities
|
|
121
|
-
// ===================================================================
|
|
122
|
-
// export {
|
|
123
|
-
// backupDbToPersistentStorage,
|
|
124
|
-
// createSigner,
|
|
125
|
-
// createUser,
|
|
126
|
-
// createXMTPClient,
|
|
127
|
-
// diagnoseXMTPIdentityIssue,
|
|
128
|
-
// generateEncryptionKeyHex,
|
|
129
|
-
// getEncryptionKeyFromHex,
|
|
130
|
-
// logAgentDetails,
|
|
131
|
-
// startPeriodicBackup,
|
|
132
|
-
// validateEnvironment
|
|
133
|
-
// } from "./client"
|
|
134
|
-
|
|
135
|
-
// ===================================================================
|
|
136
|
-
// Application Constants
|
|
137
|
-
// ===================================================================
|
|
138
|
-
export {
|
|
139
|
-
DEFAULT_AMOUNT,
|
|
140
|
-
DEFAULT_OPTIONS,
|
|
141
|
-
MAX_USDC_AMOUNT
|
|
142
|
-
} from "./constants"
|
|
143
|
-
|
|
144
|
-
export { Agent, createSigner, createUser, getTestUrl } from "@xmtp/agent-sdk"
|
|
145
|
-
|