@hybrd/xmtp 1.3.2 → 1.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/README.md +41 -7
- package/dist/index.cjs +415 -3085
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +12 -828
- package/dist/index.d.ts +12 -828
- package/dist/index.js +416 -3056
- package/dist/index.js.map +1 -1
- package/package.json +18 -5
- package/src/client.ts +23 -135
- package/src/index.ts +28 -81
- package/src/index.ts.old +145 -0
- package/src/lib/jwt.ts +45 -13
- package/src/lib/{message-listener.test.ts → message-listener.test.ts.old} +1 -1
- package/src/lib/subjects.ts +6 -5
- package/src/plugin.filters.test.ts +158 -0
- package/src/plugin.ts +456 -23
- package/src/resolver/address-resolver.ts +217 -211
- package/src/resolver/basename-resolver.ts +6 -5
- package/src/resolver/ens-resolver.ts +15 -14
- package/src/resolver/resolver.ts +3 -2
- package/src/resolver/xmtp-resolver.ts +10 -9
- package/src/{service-client.ts → service-client.ts.old} +26 -3
- package/src/types.ts +9 -157
- package/src/types.ts.old +157 -0
- package/.cache/tsbuildinfo.json +0 -1
- package/.turbo/turbo-build.log +0 -45
- package/.turbo/turbo-lint$colon$fix.log +0 -6
- package/.turbo/turbo-typecheck.log +0 -5
- package/biome.jsonc +0 -4
- package/scripts/generate-keys.ts +0 -25
- package/scripts/refresh-identity.ts +0 -119
- package/scripts/register-wallet.ts +0 -95
- package/scripts/revoke-all-installations.ts +0 -91
- package/scripts/revoke-installations.ts +0 -94
- package/src/endpoints.ts +0 -306
- package/tsconfig.json +0 -9
- package/tsup.config.ts +0 -14
- /package/src/lib/{message-listener.ts → message-listener.ts.old} +0 -0
package/src/plugin.ts
CHANGED
|
@@ -1,19 +1,65 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
1
|
+
import {
|
|
2
|
+
Agent as XmtpAgent,
|
|
3
|
+
XmtpEnv,
|
|
4
|
+
createSigner,
|
|
5
|
+
createUser
|
|
6
|
+
} from "@xmtp/agent-sdk"
|
|
7
|
+
|
|
8
|
+
import type {
|
|
9
|
+
AgentMessage,
|
|
10
|
+
AgentRuntime,
|
|
11
|
+
BehaviorContext,
|
|
12
|
+
BehaviorRegistry,
|
|
13
|
+
Plugin,
|
|
14
|
+
PluginContext,
|
|
15
|
+
XmtpClient,
|
|
16
|
+
XmtpConversation,
|
|
17
|
+
XmtpMessage
|
|
18
|
+
} from "@hybrd/types"
|
|
19
|
+
import { logger } from "@hybrd/utils"
|
|
20
|
+
import { randomUUID } from "node:crypto"
|
|
21
|
+
import { createXMTPClient, getDbPath } from "./client"
|
|
22
|
+
import { ContentTypeReply, ContentTypeText, type Reply } from "./index"
|
|
23
|
+
|
|
24
|
+
// Re-export types from @hybrd/types for backward compatibility
|
|
25
|
+
export type { Plugin }
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Send a response with threading support
|
|
29
|
+
*/
|
|
30
|
+
async function sendResponse(
|
|
31
|
+
conversation: XmtpConversation,
|
|
32
|
+
text: string,
|
|
33
|
+
originalMessageId: string,
|
|
34
|
+
behaviorContext?: BehaviorContext
|
|
35
|
+
) {
|
|
36
|
+
const shouldThread = behaviorContext?.sendOptions?.threaded ?? false
|
|
14
37
|
|
|
15
|
-
|
|
16
|
-
|
|
38
|
+
if (shouldThread) {
|
|
39
|
+
// Send as a reply to the original message
|
|
40
|
+
try {
|
|
41
|
+
const reply: Reply = {
|
|
42
|
+
reference: originalMessageId,
|
|
43
|
+
contentType: ContentTypeText,
|
|
44
|
+
content: text
|
|
45
|
+
}
|
|
46
|
+
await conversation.send(reply, ContentTypeReply)
|
|
47
|
+
logger.debug(
|
|
48
|
+
`✅ [sendResponse] Threaded reply sent successfully to message ${originalMessageId}`
|
|
49
|
+
)
|
|
50
|
+
} catch (error) {
|
|
51
|
+
logger.error(
|
|
52
|
+
`❌ [sendResponse] Failed to send threaded reply to message ${originalMessageId}:`,
|
|
53
|
+
error
|
|
54
|
+
)
|
|
55
|
+
// Fall back to regular message if threaded reply fails
|
|
56
|
+
logger.debug(`🔄 [sendResponse] Falling back to regular message`)
|
|
57
|
+
await conversation.send(text)
|
|
58
|
+
}
|
|
59
|
+
} else {
|
|
60
|
+
// Send as a regular message
|
|
61
|
+
await conversation.send(text)
|
|
62
|
+
}
|
|
17
63
|
}
|
|
18
64
|
|
|
19
65
|
/**
|
|
@@ -23,17 +69,404 @@ export interface XMTPPluginContext {
|
|
|
23
69
|
* This plugin integrates XMTP messaging capabilities into the agent's
|
|
24
70
|
* HTTP server. It mounts the XMTP endpoints for handling XMTP tools requests.
|
|
25
71
|
*/
|
|
26
|
-
export function XMTPPlugin({
|
|
27
|
-
filter
|
|
28
|
-
}: {
|
|
29
|
-
filter?: MessageListenerConfig["filter"]
|
|
30
|
-
} = {}): Plugin<XMTPPluginContext> {
|
|
72
|
+
export function XMTPPlugin(): Plugin<PluginContext> {
|
|
31
73
|
return {
|
|
32
74
|
name: "xmtp",
|
|
33
75
|
description: "Provides XMTP messaging functionality",
|
|
34
|
-
apply: (app, context) => {
|
|
35
|
-
|
|
36
|
-
|
|
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
|
|
82
|
+
|
|
83
|
+
const { agent } = context
|
|
84
|
+
const pluginContext = context as PluginContext & {
|
|
85
|
+
behaviors?: BehaviorRegistry
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (!XMTP_WALLET_KEY) {
|
|
89
|
+
throw new Error("XMTP_WALLET_KEY must be set")
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (!XMTP_DB_ENCRYPTION_KEY) {
|
|
93
|
+
throw new Error("XMTP_DB_ENCRYPTION_KEY must be set")
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const user = createUser(XMTP_WALLET_KEY as `0x${string}`)
|
|
97
|
+
const signer = createSigner(user)
|
|
98
|
+
|
|
99
|
+
const xmtpClient = await createXMTPClient(
|
|
100
|
+
XMTP_WALLET_KEY as `0x${string}`
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
// Start a reliable node client stream to process incoming messages
|
|
104
|
+
async function startNodeStream() {
|
|
105
|
+
try {
|
|
106
|
+
logger.debug("🎧 XMTP node client stream initializing")
|
|
107
|
+
const stream = await xmtpClient.conversations.streamAllMessages()
|
|
108
|
+
logger.debug("🎧 XMTP node client stream started")
|
|
109
|
+
for await (const msg of stream) {
|
|
110
|
+
try {
|
|
111
|
+
if (msg.senderInboxId === xmtpClient.inboxId) continue
|
|
112
|
+
|
|
113
|
+
const content =
|
|
114
|
+
typeof msg.content === "string"
|
|
115
|
+
? msg.content
|
|
116
|
+
: (() => {
|
|
117
|
+
try {
|
|
118
|
+
return JSON.stringify(msg.content)
|
|
119
|
+
} catch {
|
|
120
|
+
return String(msg.content)
|
|
121
|
+
}
|
|
122
|
+
})()
|
|
123
|
+
|
|
124
|
+
const conversation =
|
|
125
|
+
await xmtpClient.conversations.getConversationById(
|
|
126
|
+
msg.conversationId
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
if (!conversation) {
|
|
130
|
+
logger.warn(
|
|
131
|
+
`⚠️ XMTP conversation not found: ${msg.conversationId}`
|
|
132
|
+
)
|
|
133
|
+
continue
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const messages: AgentMessage[] = [
|
|
137
|
+
{
|
|
138
|
+
id: randomUUID(),
|
|
139
|
+
role: "user",
|
|
140
|
+
parts: [{ type: "text", text: content }]
|
|
141
|
+
}
|
|
142
|
+
]
|
|
143
|
+
|
|
144
|
+
const baseRuntime: AgentRuntime = {
|
|
145
|
+
conversation: conversation as unknown as XmtpConversation,
|
|
146
|
+
message: msg,
|
|
147
|
+
xmtpClient
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const runtime = await agent.createRuntimeContext(baseRuntime)
|
|
151
|
+
|
|
152
|
+
// Execute pre-response behaviors
|
|
153
|
+
if (pluginContext.behaviors) {
|
|
154
|
+
const behaviorContext: BehaviorContext = {
|
|
155
|
+
runtime,
|
|
156
|
+
client: xmtpClient as unknown as XmtpClient,
|
|
157
|
+
conversation: conversation as unknown as XmtpConversation,
|
|
158
|
+
message: msg as XmtpMessage
|
|
159
|
+
}
|
|
160
|
+
await pluginContext.behaviors.executeBefore(behaviorContext)
|
|
161
|
+
|
|
162
|
+
// Check if message was filtered out by any behavior
|
|
163
|
+
if (behaviorContext.sendOptions?.filtered) {
|
|
164
|
+
continue // Skip processing this message
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const { text } = await agent.generate(messages, { runtime })
|
|
169
|
+
|
|
170
|
+
// Create behavior context for send options
|
|
171
|
+
const behaviorContext: BehaviorContext = {
|
|
172
|
+
runtime,
|
|
173
|
+
client: xmtpClient as unknown as XmtpClient,
|
|
174
|
+
conversation: conversation as unknown as XmtpConversation,
|
|
175
|
+
message: msg as XmtpMessage,
|
|
176
|
+
response: text
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Execute post-response behaviors
|
|
180
|
+
if (pluginContext.behaviors) {
|
|
181
|
+
await pluginContext.behaviors.executeAfter(behaviorContext)
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Check if message was filtered out by filterMessages behavior
|
|
185
|
+
if (behaviorContext?.sendOptions?.filtered) {
|
|
186
|
+
logger.debug(
|
|
187
|
+
`🔇 [XMTP Plugin] Skipping response due to message being filtered`
|
|
188
|
+
)
|
|
189
|
+
return
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Send the response with threading support
|
|
193
|
+
await sendResponse(conversation, text, msg.id, behaviorContext)
|
|
194
|
+
} catch (err) {
|
|
195
|
+
logger.error("❌ Error processing XMTP message:", err)
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
} catch (err) {
|
|
199
|
+
logger.error("❌ XMTP node client stream failed:", err)
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const enabledFromEnv = process.env.XMTP_ENABLE_NODE_STREAM
|
|
204
|
+
const isNodeStreamEnabled =
|
|
205
|
+
enabledFromEnv === undefined
|
|
206
|
+
? true
|
|
207
|
+
: !/^(false|0|off|no)$/i.test(String(enabledFromEnv))
|
|
208
|
+
|
|
209
|
+
if (isNodeStreamEnabled) void startNodeStream()
|
|
210
|
+
|
|
211
|
+
const address = user.account.address.toLowerCase()
|
|
212
|
+
const agentDbPath = await getDbPath(
|
|
213
|
+
`agent-${XMTP_ENV || "dev"}-${address}`
|
|
214
|
+
)
|
|
215
|
+
logger.debug(`📁 Using agent listener database path: ${agentDbPath}`)
|
|
216
|
+
|
|
217
|
+
const xmtp = await XmtpAgent.create(signer, {
|
|
218
|
+
env: XMTP_ENV as XmtpEnv,
|
|
219
|
+
dbPath: agentDbPath
|
|
220
|
+
})
|
|
221
|
+
|
|
222
|
+
xmtp.on("reaction", async ({ conversation, message }) => {
|
|
223
|
+
try {
|
|
224
|
+
const text = message.content.content
|
|
225
|
+
const messages: AgentMessage[] = [
|
|
226
|
+
{
|
|
227
|
+
id: randomUUID(),
|
|
228
|
+
role: "user",
|
|
229
|
+
parts: [{ type: "text", text }]
|
|
230
|
+
}
|
|
231
|
+
]
|
|
232
|
+
|
|
233
|
+
const baseRuntime: AgentRuntime = {
|
|
234
|
+
conversation: conversation as unknown as XmtpConversation,
|
|
235
|
+
message: message as unknown as XmtpMessage,
|
|
236
|
+
xmtpClient
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
const runtime = await agent.createRuntimeContext(baseRuntime)
|
|
240
|
+
|
|
241
|
+
// Execute pre-response behaviors
|
|
242
|
+
if (context.behaviors) {
|
|
243
|
+
const behaviorContext: BehaviorContext = {
|
|
244
|
+
runtime,
|
|
245
|
+
client: xmtpClient as unknown as XmtpClient,
|
|
246
|
+
conversation: conversation as unknown as XmtpConversation,
|
|
247
|
+
message: message as unknown as XmtpMessage
|
|
248
|
+
}
|
|
249
|
+
await context.behaviors.executeBefore(behaviorContext)
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
const { text: reply } = await agent.generate(messages, { runtime })
|
|
253
|
+
|
|
254
|
+
// Execute post-response behaviors
|
|
255
|
+
let behaviorContext: BehaviorContext | undefined
|
|
256
|
+
if (context.behaviors) {
|
|
257
|
+
behaviorContext = {
|
|
258
|
+
runtime,
|
|
259
|
+
client: xmtpClient as unknown as XmtpClient,
|
|
260
|
+
conversation: conversation as unknown as XmtpConversation,
|
|
261
|
+
message: message as unknown as XmtpMessage,
|
|
262
|
+
response: reply
|
|
263
|
+
}
|
|
264
|
+
await context.behaviors.executeAfter(behaviorContext)
|
|
265
|
+
} else {
|
|
266
|
+
// Create minimal context for send options
|
|
267
|
+
behaviorContext = {
|
|
268
|
+
runtime,
|
|
269
|
+
client: xmtpClient as unknown as XmtpClient,
|
|
270
|
+
conversation: conversation as unknown as XmtpConversation,
|
|
271
|
+
message: message as unknown as XmtpMessage,
|
|
272
|
+
response: reply
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// Check if message was filtered out by filterMessages behavior
|
|
277
|
+
if (behaviorContext?.sendOptions?.filtered) {
|
|
278
|
+
logger.debug(
|
|
279
|
+
`🔇 [XMTP Plugin] Skipping reaction response due to message being filtered`
|
|
280
|
+
)
|
|
281
|
+
return
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
await sendResponse(
|
|
285
|
+
conversation as unknown as XmtpConversation,
|
|
286
|
+
reply,
|
|
287
|
+
message.id,
|
|
288
|
+
behaviorContext
|
|
289
|
+
)
|
|
290
|
+
} catch (err) {
|
|
291
|
+
logger.error("❌ Error handling reaction:", err)
|
|
292
|
+
}
|
|
293
|
+
})
|
|
294
|
+
|
|
295
|
+
xmtp.on("reply", async ({ conversation, message }) => {
|
|
296
|
+
try {
|
|
297
|
+
// TODO - why isn't this typed better?
|
|
298
|
+
const text = message.content.content as string
|
|
299
|
+
const messages: AgentMessage[] = [
|
|
300
|
+
{
|
|
301
|
+
id: randomUUID(),
|
|
302
|
+
role: "user",
|
|
303
|
+
parts: [{ type: "text", text }]
|
|
304
|
+
}
|
|
305
|
+
]
|
|
306
|
+
|
|
307
|
+
const baseRuntime: AgentRuntime = {
|
|
308
|
+
conversation: conversation as unknown as XmtpConversation,
|
|
309
|
+
message: message as unknown as XmtpMessage,
|
|
310
|
+
xmtpClient
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
const runtime = await agent.createRuntimeContext(baseRuntime)
|
|
314
|
+
|
|
315
|
+
// Execute pre-response behaviors
|
|
316
|
+
let behaviorContext: BehaviorContext | undefined
|
|
317
|
+
if (context.behaviors) {
|
|
318
|
+
behaviorContext = {
|
|
319
|
+
runtime,
|
|
320
|
+
client: xmtpClient as unknown as XmtpClient,
|
|
321
|
+
conversation: conversation as unknown as XmtpConversation,
|
|
322
|
+
message: message as unknown as XmtpMessage
|
|
323
|
+
}
|
|
324
|
+
await context.behaviors.executeBefore(behaviorContext)
|
|
325
|
+
|
|
326
|
+
// Check if behaviors were stopped early (e.g., due to filtering)
|
|
327
|
+
if (behaviorContext.stopped) {
|
|
328
|
+
logger.debug(
|
|
329
|
+
`🔇 [XMTP Plugin] Skipping reply response due to behavior chain being stopped`
|
|
330
|
+
)
|
|
331
|
+
return
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
const { text: reply } = await agent.generate(messages, { runtime })
|
|
336
|
+
|
|
337
|
+
// Execute post-response behaviors
|
|
338
|
+
if (context.behaviors) {
|
|
339
|
+
if (!behaviorContext) {
|
|
340
|
+
behaviorContext = {
|
|
341
|
+
runtime,
|
|
342
|
+
client: xmtpClient as unknown as XmtpClient,
|
|
343
|
+
conversation: conversation as unknown as XmtpConversation,
|
|
344
|
+
message: message as unknown as XmtpMessage,
|
|
345
|
+
response: reply
|
|
346
|
+
}
|
|
347
|
+
} else {
|
|
348
|
+
behaviorContext.response = reply
|
|
349
|
+
}
|
|
350
|
+
await context.behaviors.executeAfter(behaviorContext)
|
|
351
|
+
|
|
352
|
+
// Check if post behaviors were stopped early
|
|
353
|
+
if (behaviorContext.stopped) {
|
|
354
|
+
logger.debug(
|
|
355
|
+
`🔇 [XMTP Plugin] Skipping reply response due to post-behavior chain being stopped`
|
|
356
|
+
)
|
|
357
|
+
return
|
|
358
|
+
}
|
|
359
|
+
} else {
|
|
360
|
+
// Create minimal context for send options
|
|
361
|
+
behaviorContext = {
|
|
362
|
+
runtime,
|
|
363
|
+
client: xmtpClient as unknown as XmtpClient,
|
|
364
|
+
conversation: conversation as unknown as XmtpConversation,
|
|
365
|
+
message: message as unknown as XmtpMessage,
|
|
366
|
+
response: reply
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
await sendResponse(
|
|
371
|
+
conversation as unknown as XmtpConversation,
|
|
372
|
+
reply,
|
|
373
|
+
message.id,
|
|
374
|
+
behaviorContext
|
|
375
|
+
)
|
|
376
|
+
} catch (err) {
|
|
377
|
+
logger.error("❌ Error handling reply:", err)
|
|
378
|
+
}
|
|
379
|
+
})
|
|
380
|
+
|
|
381
|
+
xmtp.on("text", async ({ conversation, message }) => {
|
|
382
|
+
try {
|
|
383
|
+
const text = message.content
|
|
384
|
+
const messages: AgentMessage[] = [
|
|
385
|
+
{ id: randomUUID(), role: "user", parts: [{ type: "text", text }] }
|
|
386
|
+
]
|
|
387
|
+
|
|
388
|
+
const baseRuntime: AgentRuntime = {
|
|
389
|
+
conversation: conversation as unknown as XmtpConversation,
|
|
390
|
+
message: message as unknown as XmtpMessage,
|
|
391
|
+
xmtpClient
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
const runtime = await agent.createRuntimeContext(baseRuntime)
|
|
395
|
+
|
|
396
|
+
// Execute pre-response behaviors
|
|
397
|
+
let behaviorContext: BehaviorContext | undefined
|
|
398
|
+
if (context.behaviors) {
|
|
399
|
+
behaviorContext = {
|
|
400
|
+
runtime,
|
|
401
|
+
client: xmtpClient as unknown as XmtpClient,
|
|
402
|
+
conversation: conversation as unknown as XmtpConversation,
|
|
403
|
+
message: message as unknown as XmtpMessage
|
|
404
|
+
}
|
|
405
|
+
await context.behaviors.executeBefore(behaviorContext)
|
|
406
|
+
|
|
407
|
+
// Check if behaviors were stopped early (e.g., due to filtering)
|
|
408
|
+
if (behaviorContext.stopped) {
|
|
409
|
+
logger.debug(
|
|
410
|
+
`🔇 [XMTP Plugin] Skipping text response due to behavior chain being stopped`
|
|
411
|
+
)
|
|
412
|
+
return
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
const { text: reply } = await agent.generate(messages, { runtime })
|
|
417
|
+
|
|
418
|
+
// Execute post-response behaviors
|
|
419
|
+
if (context.behaviors) {
|
|
420
|
+
if (!behaviorContext) {
|
|
421
|
+
behaviorContext = {
|
|
422
|
+
runtime,
|
|
423
|
+
client: xmtpClient as unknown as XmtpClient,
|
|
424
|
+
conversation: conversation as unknown as XmtpConversation,
|
|
425
|
+
message: message as unknown as XmtpMessage,
|
|
426
|
+
response: reply
|
|
427
|
+
}
|
|
428
|
+
} else {
|
|
429
|
+
behaviorContext.response = reply
|
|
430
|
+
}
|
|
431
|
+
await context.behaviors.executeAfter(behaviorContext)
|
|
432
|
+
|
|
433
|
+
// Check if post behaviors were stopped early
|
|
434
|
+
if (behaviorContext.stopped) {
|
|
435
|
+
logger.debug(
|
|
436
|
+
`🔇 [XMTP Plugin] Skipping text response due to post-behavior chain being stopped`
|
|
437
|
+
)
|
|
438
|
+
return
|
|
439
|
+
}
|
|
440
|
+
} else {
|
|
441
|
+
// Create minimal context for send options
|
|
442
|
+
behaviorContext = {
|
|
443
|
+
runtime,
|
|
444
|
+
client: xmtpClient as unknown as XmtpClient,
|
|
445
|
+
conversation: conversation as unknown as XmtpConversation,
|
|
446
|
+
message: message as unknown as XmtpMessage,
|
|
447
|
+
response: reply
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
await sendResponse(
|
|
452
|
+
conversation as unknown as XmtpConversation,
|
|
453
|
+
reply,
|
|
454
|
+
message.id,
|
|
455
|
+
behaviorContext
|
|
456
|
+
)
|
|
457
|
+
} catch (err) {
|
|
458
|
+
logger.error("❌ Error handling text:", err)
|
|
459
|
+
}
|
|
460
|
+
})
|
|
461
|
+
|
|
462
|
+
// Event handlers removed due to incompatibility with current XMTP agent SDK
|
|
463
|
+
|
|
464
|
+
void xmtp
|
|
465
|
+
.start()
|
|
466
|
+
.then(() => logger.debug("✅ XMTP agent listener started"))
|
|
467
|
+
.catch((err) =>
|
|
468
|
+
console.error("❌ XMTP agent listener failed to start:", err)
|
|
469
|
+
)
|
|
37
470
|
}
|
|
38
471
|
}
|
|
39
472
|
}
|