@elizaos/plugin-farcaster 1.0.5 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/README.md +42 -1
  2. package/dist/__tests__/e2e/scenarios.d.ts +4 -0
  3. package/dist/__tests__/e2e/scenarios.d.ts.map +1 -0
  4. package/dist/__tests__/suite.d.ts +117 -0
  5. package/dist/__tests__/suite.d.ts.map +1 -0
  6. package/dist/__tests__/test-utils.d.ts +29 -0
  7. package/dist/__tests__/test-utils.d.ts.map +1 -0
  8. package/dist/__tests__/types.d.ts +88 -0
  9. package/dist/__tests__/types.d.ts.map +1 -0
  10. package/dist/actions/index.d.ts +4 -0
  11. package/dist/actions/index.d.ts.map +1 -0
  12. package/dist/actions/replyCast.d.ts +3 -0
  13. package/dist/actions/replyCast.d.ts.map +1 -0
  14. package/dist/actions/sendCast.d.ts +3 -0
  15. package/dist/actions/sendCast.d.ts.map +1 -0
  16. package/dist/client.d.ts +26 -0
  17. package/dist/client.d.ts.map +1 -0
  18. package/dist/common/asyncqueue.d.ts +13 -0
  19. package/dist/common/asyncqueue.d.ts.map +1 -0
  20. package/dist/common/callbacks.d.ts +14 -0
  21. package/dist/common/callbacks.d.ts.map +1 -0
  22. package/dist/common/config.d.ts +15 -0
  23. package/dist/common/config.d.ts.map +1 -0
  24. package/dist/common/constants.d.ts +9 -0
  25. package/dist/common/constants.d.ts.map +1 -0
  26. package/dist/common/prompts.d.ts +5 -0
  27. package/dist/common/prompts.d.ts.map +1 -0
  28. package/dist/common/types.d.ts +80 -0
  29. package/dist/common/types.d.ts.map +1 -0
  30. package/dist/common/utils.d.ts +24 -0
  31. package/dist/common/utils.d.ts.map +1 -0
  32. package/dist/events/messageHandler.d.ts +29 -0
  33. package/dist/events/messageHandler.d.ts.map +1 -0
  34. package/dist/index.d.ts +7 -500
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +1050 -739
  37. package/dist/index.js.map +35 -1
  38. package/dist/managers/agent.d.ts +21 -0
  39. package/dist/managers/agent.d.ts.map +1 -0
  40. package/dist/managers/interaction-processor.d.ts +12 -0
  41. package/dist/managers/interaction-processor.d.ts.map +1 -0
  42. package/dist/managers/interaction-source.d.ts +50 -0
  43. package/dist/managers/interaction-source.d.ts.map +1 -0
  44. package/dist/managers/interactions.d.ts +49 -0
  45. package/dist/managers/interactions.d.ts.map +1 -0
  46. package/dist/managers/post.d.ts +24 -0
  47. package/dist/managers/post.d.ts.map +1 -0
  48. package/dist/providers/index.d.ts +5 -0
  49. package/dist/providers/index.d.ts.map +1 -0
  50. package/dist/providers/profileProvider.d.ts +3 -0
  51. package/dist/providers/profileProvider.d.ts.map +1 -0
  52. package/dist/providers/threadProvider.d.ts +3 -0
  53. package/dist/providers/threadProvider.d.ts.map +1 -0
  54. package/dist/providers/timelineProvider.d.ts +3 -0
  55. package/dist/providers/timelineProvider.d.ts.map +1 -0
  56. package/dist/routes/webhook.d.ts +3 -0
  57. package/dist/routes/webhook.d.ts.map +1 -0
  58. package/dist/service.d.ts +31 -0
  59. package/dist/service.d.ts.map +1 -0
  60. package/dist/services/CastService.d.ts +142 -0
  61. package/dist/services/CastService.d.ts.map +1 -0
  62. package/dist/services/MessageService.d.ts +50 -0
  63. package/dist/services/MessageService.d.ts.map +1 -0
  64. package/package.json +5 -6
  65. package/dist/chunk-FNDASAYG.js +0 -83
  66. package/dist/chunk-FNDASAYG.js.map +0 -1
  67. package/dist/chunk-IOTLJXKN.js +0 -72
  68. package/dist/chunk-IOTLJXKN.js.map +0 -1
  69. package/dist/chunk-OAXQ6Z2Q.js +0 -105
  70. package/dist/chunk-OAXQ6Z2Q.js.map +0 -1
  71. package/dist/chunk-Y2URJ4EZ.js +0 -21
  72. package/dist/chunk-Y2URJ4EZ.js.map +0 -1
  73. package/dist/profileProvider-TNRU42OO.js +0 -8
  74. package/dist/profileProvider-TNRU42OO.js.map +0 -1
  75. package/dist/sendCast-OW6DBKQB.js +0 -8
  76. package/dist/sendCast-OW6DBKQB.js.map +0 -1
  77. package/dist/timelineProvider-GPRPFEVJ.js +0 -8
  78. package/dist/timelineProvider-GPRPFEVJ.js.map +0 -1
package/dist/index.js CHANGED
@@ -1,37 +1,287 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __export = (target, all) => {
3
+ for (var name in all)
4
+ __defProp(target, name, {
5
+ get: all[name],
6
+ enumerable: true,
7
+ configurable: true,
8
+ set: (newValue) => all[name] = () => newValue
9
+ });
10
+ };
11
+ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
12
+
13
+ // src/common/constants.ts
14
+ var FARCASTER_SERVICE_NAME = "farcaster", FARCASTER_SOURCE = "farcaster", DEFAULT_MAX_CAST_LENGTH = 320, DEFAULT_POLL_INTERVAL = 120, DEFAULT_CAST_INTERVAL_MIN = 90, DEFAULT_CAST_INTERVAL_MAX = 180, DEFAULT_CAST_CACHE_TTL, DEFAULT_CAST_CACHE_SIZE = 9000;
15
+ var init_constants = __esm(() => {
16
+ DEFAULT_CAST_CACHE_TTL = 1000 * 30 * 60;
17
+ });
18
+
19
+ // src/actions/sendCast.ts
20
+ var exports_sendCast = {};
21
+ __export(exports_sendCast, {
22
+ sendCastAction: () => sendCastAction
23
+ });
1
24
  import {
2
- sendCastAction
3
- } from "./chunk-OAXQ6Z2Q.js";
4
- import {
5
- farcasterProfileProvider
6
- } from "./chunk-IOTLJXKN.js";
7
- import {
8
- farcasterTimelineProvider
9
- } from "./chunk-FNDASAYG.js";
10
- import {
11
- DEFAULT_CAST_CACHE_SIZE,
12
- DEFAULT_CAST_CACHE_TTL,
13
- DEFAULT_CAST_INTERVAL_MAX,
14
- DEFAULT_CAST_INTERVAL_MIN,
15
- DEFAULT_MAX_CAST_LENGTH,
16
- DEFAULT_POLL_INTERVAL,
17
- FARCASTER_SERVICE_NAME,
18
- FARCASTER_SOURCE
19
- } from "./chunk-Y2URJ4EZ.js";
25
+ logger as logger8,
26
+ createUniqueUuid as createUniqueUuid5
27
+ } from "@elizaos/core";
28
+ var sendCastAction;
29
+ var init_sendCast = __esm(() => {
30
+ init_constants();
31
+ sendCastAction = {
32
+ name: "SEND_CAST",
33
+ description: "Posts a cast (message) on Farcaster",
34
+ examples: [
35
+ [
36
+ {
37
+ name: "user",
38
+ content: { text: "Can you post about the new ElizaOS features on Farcaster?" }
39
+ },
40
+ {
41
+ name: "assistant",
42
+ content: {
43
+ text: "I'll post about the new ElizaOS features on Farcaster now.",
44
+ actions: ["SEND_CAST"]
45
+ }
46
+ }
47
+ ],
48
+ [
49
+ {
50
+ name: "user",
51
+ content: { text: "Share on Farcaster that we just launched version 2.0!" }
52
+ },
53
+ {
54
+ name: "assistant",
55
+ content: {
56
+ text: "I'll share the version 2.0 launch announcement on Farcaster.",
57
+ actions: ["SEND_CAST"]
58
+ }
59
+ }
60
+ ]
61
+ ],
62
+ validate: async (runtime, message) => {
63
+ const text = message.content.text?.toLowerCase() || "";
64
+ const keywords = ["post", "cast", "share", "announce", "farcaster", "tweet"];
65
+ const hasKeyword = keywords.some((keyword) => text.includes(keyword));
66
+ const service = runtime.getService(FARCASTER_SERVICE_NAME);
67
+ const isServiceAvailable = !!service?.getCastService(runtime.agentId);
68
+ return hasKeyword && isServiceAvailable;
69
+ },
70
+ handler: async (runtime, message, state) => {
71
+ try {
72
+ const service = runtime.getService(FARCASTER_SERVICE_NAME);
73
+ const postService = service?.getCastService(runtime.agentId);
74
+ if (!postService) {
75
+ runtime.logger.error("[SEND_CAST] PostService not available");
76
+ return;
77
+ }
78
+ let castContent = "";
79
+ if (state?.castContent) {
80
+ castContent = state.castContent;
81
+ } else {
82
+ const prompt = `Based on this request: "${message.content.text}", generate a concise Farcaster cast (max 320 characters). Be engaging and use appropriate hashtags if relevant.`;
83
+ const response = await runtime.useModel("text_large", { prompt });
84
+ castContent = typeof response === "string" ? response : response.text || "";
85
+ }
86
+ if (castContent.length > 320) {
87
+ castContent = castContent.substring(0, 317) + "...";
88
+ }
89
+ const cast = await postService.createCast({
90
+ agentId: runtime.agentId,
91
+ roomId: createUniqueUuid5(runtime, "farcaster-timeline"),
92
+ text: castContent
93
+ });
94
+ logger8.info(`[SEND_CAST] Successfully posted cast: ${cast.id}`);
95
+ await runtime.createMemory({
96
+ agentId: runtime.agentId,
97
+ roomId: cast.roomId,
98
+ entityId: runtime.agentId,
99
+ content: {
100
+ text: castContent,
101
+ source: "farcaster",
102
+ metadata: {
103
+ castHash: cast.metadata?.castHash,
104
+ action: "SEND_CAST"
105
+ }
106
+ },
107
+ createdAt: cast.timestamp
108
+ }, "messages");
109
+ } catch (error) {
110
+ runtime.logger.error("[SEND_CAST] Error posting cast:", typeof error === "string" ? error : error.message);
111
+ throw error;
112
+ }
113
+ }
114
+ };
115
+ });
116
+
117
+ // src/providers/profileProvider.ts
118
+ var exports_profileProvider = {};
119
+ __export(exports_profileProvider, {
120
+ farcasterProfileProvider: () => farcasterProfileProvider
121
+ });
122
+ var farcasterProfileProvider;
123
+ var init_profileProvider = __esm(() => {
124
+ init_constants();
125
+ farcasterProfileProvider = {
126
+ name: "farcasterProfile",
127
+ description: "Provides information about the agent's Farcaster profile",
128
+ get: async (runtime, message, state) => {
129
+ try {
130
+ const service = runtime.getService(FARCASTER_SERVICE_NAME);
131
+ const managers = service?.getActiveManagers();
132
+ if (!managers || managers.size === 0) {
133
+ runtime.logger.debug("[FarcasterProfileProvider] No managers available");
134
+ return {
135
+ text: "Farcaster profile not available.",
136
+ data: { available: false }
137
+ };
138
+ }
139
+ const manager = managers.get(runtime.agentId);
140
+ if (!manager) {
141
+ runtime.logger.debug("[FarcasterProfileProvider] No manager for this agent");
142
+ return {
143
+ text: "Farcaster profile not available for this agent.",
144
+ data: { available: false }
145
+ };
146
+ }
147
+ const fid = parseInt(runtime.getSetting("FARCASTER_FID"), 10);
148
+ if (!fid || isNaN(fid)) {
149
+ runtime.logger.warn("[FarcasterProfileProvider] Invalid or missing FARCASTER_FID");
150
+ return {
151
+ text: "Invalid Farcaster FID configured.",
152
+ data: { available: false, error: "Invalid FID" }
153
+ };
154
+ }
155
+ try {
156
+ const profile = await manager.client.getProfile(fid);
157
+ return {
158
+ text: `Your Farcaster profile: @${profile.username} (FID: ${profile.fid}). ${profile.name ? `Display name: ${profile.name}` : ""}`,
159
+ data: {
160
+ available: true,
161
+ fid: profile.fid,
162
+ username: profile.username,
163
+ name: profile.name,
164
+ pfp: profile.pfp
165
+ },
166
+ values: {
167
+ fid: profile.fid,
168
+ username: profile.username
169
+ }
170
+ };
171
+ } catch (error) {
172
+ runtime.logger.error("[FarcasterProfileProvider] Error fetching profile:", typeof error === "string" ? error : error.message);
173
+ return {
174
+ text: "Unable to fetch Farcaster profile at this time.",
175
+ data: { available: false, error: "Fetch failed" }
176
+ };
177
+ }
178
+ } catch (error) {
179
+ runtime.logger.error("[FarcasterProfileProvider] Error:", typeof error === "string" ? error : error.message);
180
+ return {
181
+ text: "Farcaster service is not available.",
182
+ data: { available: false }
183
+ };
184
+ }
185
+ }
186
+ };
187
+ });
188
+
189
+ // src/providers/timelineProvider.ts
190
+ var exports_timelineProvider = {};
191
+ __export(exports_timelineProvider, {
192
+ farcasterTimelineProvider: () => farcasterTimelineProvider
193
+ });
194
+ function getTimeAgo(date) {
195
+ const seconds = Math.floor((new Date().getTime() - date.getTime()) / 1000);
196
+ if (seconds < 60)
197
+ return "just now";
198
+ if (seconds < 3600)
199
+ return `${Math.floor(seconds / 60)}m ago`;
200
+ if (seconds < 86400)
201
+ return `${Math.floor(seconds / 3600)}h ago`;
202
+ return `${Math.floor(seconds / 86400)}d ago`;
203
+ }
204
+ var farcasterTimelineProvider;
205
+ var init_timelineProvider = __esm(() => {
206
+ init_constants();
207
+ farcasterTimelineProvider = {
208
+ name: "farcasterTimeline",
209
+ description: "Provides recent casts from the agent's Farcaster timeline",
210
+ get: async (runtime, message, state) => {
211
+ try {
212
+ const service = runtime.getService(FARCASTER_SERVICE_NAME);
213
+ const castService = service?.getCastService(runtime.agentId);
214
+ if (!castService) {
215
+ return {
216
+ text: "Farcaster timeline not available.",
217
+ data: { available: false }
218
+ };
219
+ }
220
+ const casts = await castService.getCasts({
221
+ agentId: runtime.agentId,
222
+ limit: 5
223
+ });
224
+ if (!casts || casts.length === 0) {
225
+ return {
226
+ text: "No recent casts in your timeline.",
227
+ data: {
228
+ available: true,
229
+ casts: [],
230
+ count: 0
231
+ }
232
+ };
233
+ }
234
+ const formattedCasts = casts.map((cast, index) => {
235
+ const timeAgo = getTimeAgo(new Date(cast.timestamp));
236
+ return `${index + 1}. @${cast.username} (${timeAgo}): ${cast.text}`;
237
+ }).join(`
238
+ `);
239
+ return {
240
+ text: `Recent casts from your timeline:
241
+ ${formattedCasts}`,
242
+ data: {
243
+ available: true,
244
+ casts: casts.map((c) => ({
245
+ id: c.id,
246
+ username: c.username,
247
+ text: c.text,
248
+ timestamp: c.timestamp,
249
+ castHash: c.metadata?.castHash
250
+ })),
251
+ count: casts.length
252
+ },
253
+ values: {
254
+ latestCastHash: casts[0]?.metadata?.castHash,
255
+ latestCastText: casts[0]?.text
256
+ }
257
+ };
258
+ } catch (error) {
259
+ runtime.logger.error("[FarcasterTimelineProvider] Error:", typeof error === "string" ? error : error.message);
260
+ return {
261
+ text: "Unable to fetch Farcaster timeline.",
262
+ data: { available: false, error: error instanceof Error ? error.message : "Unknown error" }
263
+ };
264
+ }
265
+ }
266
+ };
267
+ });
20
268
 
21
269
  // src/service.ts
22
- import { logger as logger8, Service } from "@elizaos/core";
270
+ init_constants();
271
+ import { logger as logger7, Service } from "@elizaos/core";
23
272
 
24
273
  // src/managers/agent.ts
25
274
  import { logger as logger4 } from "@elizaos/core";
26
275
  import { Configuration, NeynarAPIClient } from "@neynar/nodejs-sdk";
27
276
 
28
277
  // src/client.ts
278
+ init_constants();
29
279
  import { elizaLogger } from "@elizaos/core";
30
280
  import { isApiErrorResponse } from "@neynar/nodejs-sdk";
31
- import { CastParamType } from "@neynar/nodejs-sdk/build/api/index.js";
32
281
  import { LRUCache } from "lru-cache";
33
282
 
34
283
  // src/common/utils.ts
284
+ init_constants();
35
285
  import { stringToUuid } from "@elizaos/core";
36
286
  var MAX_CAST_LENGTH = 1024;
37
287
  function castId({ hash, agentId }) {
@@ -41,14 +291,21 @@ function castUuid(props) {
41
291
  return stringToUuid(castId(props));
42
292
  }
43
293
  function splitPostContent(content, maxLength = MAX_CAST_LENGTH) {
44
- const paragraphs = content.split("\n\n").map((p) => p.trim());
294
+ const paragraphs = content.split(`
295
+
296
+ `).map((p) => p.trim());
45
297
  const posts = [];
46
298
  let currentCast = "";
47
299
  for (const paragraph of paragraphs) {
48
- if (!paragraph) continue;
49
- if ((currentCast + "\n\n" + paragraph).trim().length <= maxLength) {
300
+ if (!paragraph)
301
+ continue;
302
+ if ((currentCast + `
303
+
304
+ ` + paragraph).trim().length <= maxLength) {
50
305
  if (currentCast) {
51
- currentCast += "\n\n" + paragraph;
306
+ currentCast += `
307
+
308
+ ` + paragraph;
52
309
  } else {
53
310
  currentCast = paragraph;
54
311
  }
@@ -116,18 +373,17 @@ function lastCastCacheKey(fid) {
116
373
  return `farcaster/${fid}/lastCast`;
117
374
  }
118
375
  function neynarCastToCast(neynarCast) {
119
- var _a;
120
376
  return {
121
377
  hash: neynarCast.hash,
122
378
  authorFid: neynarCast.author.fid,
123
379
  text: neynarCast.text,
124
- threadId: neynarCast.thread_hash ?? void 0,
380
+ threadId: neynarCast.thread_hash ?? undefined,
125
381
  profile: {
126
382
  fid: neynarCast.author.fid,
127
383
  name: neynarCast.author.display_name || "anon",
128
384
  username: neynarCast.author.username
129
385
  },
130
- ...neynarCast.parent_hash && ((_a = neynarCast.parent_author) == null ? void 0 : _a.fid) ? {
386
+ ...neynarCast.parent_hash && neynarCast.parent_author?.fid ? {
131
387
  inReplyTo: {
132
388
  hash: neynarCast.parent_hash,
133
389
  fid: neynarCast.parent_author.fid
@@ -145,7 +401,7 @@ function createCastMemory({
145
401
  const inReplyTo = cast.inReplyTo ? castUuid({
146
402
  hash: cast.inReplyTo.hash,
147
403
  agentId: runtime.agentId
148
- }) : void 0;
404
+ }) : undefined;
149
405
  return {
150
406
  id: castUuid({
151
407
  hash: cast.hash,
@@ -164,14 +420,6 @@ function createCastMemory({
164
420
  roomId
165
421
  };
166
422
  }
167
- function formatCastTimestamp(timestamp) {
168
- return timestamp.toLocaleString("en-US", {
169
- hour: "2-digit",
170
- minute: "2-digit",
171
- month: "short",
172
- day: "numeric"
173
- });
174
- }
175
423
 
176
424
  // src/client.ts
177
425
  var castCache = new LRUCache({
@@ -179,11 +427,11 @@ var castCache = new LRUCache({
179
427
  ttl: DEFAULT_CAST_CACHE_TTL
180
428
  });
181
429
  var profileCache = new LRUCache({
182
- max: 1e3,
183
- ttl: 1e3 * 60 * 15
184
- // 15 minutes
430
+ max: 1000,
431
+ ttl: 1000 * 60 * 15
185
432
  });
186
- var FarcasterClient = class {
433
+
434
+ class FarcasterClient {
187
435
  neynar;
188
436
  signerUuid;
189
437
  constructor(opts) {
@@ -211,7 +459,7 @@ var FarcasterClient = class {
211
459
  const result = await this.neynar.publishCast({
212
460
  signerUuid: this.signerUuid,
213
461
  text: cast,
214
- parent: parentCastId == null ? void 0 : parentCastId.hash
462
+ parent: parentCastId?.hash
215
463
  });
216
464
  if (result.success) {
217
465
  return this.getCast(result.cast.hash);
@@ -219,10 +467,10 @@ var FarcasterClient = class {
219
467
  throw new Error(`[Farcaster] Error publishing [${cast}] parentCastId: [${parentCastId}]`);
220
468
  } catch (err) {
221
469
  if (isApiErrorResponse(err)) {
222
- elizaLogger.error("Neynar error: ", err.response.data);
470
+ elizaLogger.error(`Neynar error: ${JSON.stringify(err.response.data)}`);
223
471
  throw err.response.data;
224
472
  } else {
225
- elizaLogger.error("Error: ", err);
473
+ elizaLogger.error(`Error: ${JSON.stringify(err)}`);
226
474
  throw err;
227
475
  }
228
476
  }
@@ -232,8 +480,7 @@ var FarcasterClient = class {
232
480
  if (cachedCast) {
233
481
  return cachedCast;
234
482
  }
235
- const params = { identifier: castHash, type: CastParamType.Hash };
236
- const response = await this.neynar.lookupCastByHashOrWarpcastUrl(params);
483
+ const response = await this.neynar.lookupCastByHashOrUrl({ identifier: castHash, type: "hash" });
237
484
  castCache.set(castHash, response.cast);
238
485
  return response.cast;
239
486
  }
@@ -275,12 +522,11 @@ var FarcasterClient = class {
275
522
  profileCache.set(fid, profile);
276
523
  return profile;
277
524
  } catch (error) {
278
- elizaLogger.error("Error fetching profile:", error);
525
+ elizaLogger.error(`Error fetching profile: ${JSON.stringify(error)}`);
279
526
  throw error;
280
527
  }
281
528
  }
282
529
  async getTimeline(request) {
283
- var _a;
284
530
  const timeline = [];
285
531
  const response = await this.neynar.fetchCastsForUser({
286
532
  fid: request.fid,
@@ -290,7 +536,7 @@ var FarcasterClient = class {
290
536
  castCache.set(cast.hash, cast);
291
537
  timeline.push(neynarCastToCast(cast));
292
538
  }
293
- const nextCursor = ((_a = response.next) == null ? void 0 : _a.cursor) ?? void 0;
539
+ const nextCursor = response.next?.cursor ?? undefined;
294
540
  return {
295
541
  timeline,
296
542
  cursor: nextCursor
@@ -300,78 +546,10 @@ var FarcasterClient = class {
300
546
  profileCache.clear();
301
547
  castCache.clear();
302
548
  }
303
- };
304
-
305
- // src/managers/interactions.ts
306
- import {
307
- ChannelType,
308
- composePrompt,
309
- createUniqueUuid,
310
- EventType,
311
- logger as logger2,
312
- ModelType
313
- } from "@elizaos/core";
549
+ }
314
550
 
315
- // src/common/asyncqueue.ts
316
- var AsyncQueue = class {
317
- queue = [];
318
- running = 0;
319
- emptyListeners = [];
320
- maxConcurrent;
321
- constructor(maxConcurrent = 1) {
322
- this.maxConcurrent = maxConcurrent;
323
- }
324
- async submit(work) {
325
- return new Promise((resolve, reject) => {
326
- this.queue.push(async () => {
327
- try {
328
- resolve(await work());
329
- } catch (err) {
330
- reject(err);
331
- }
332
- });
333
- void this.doNextWork();
334
- });
335
- }
336
- async doNextWork() {
337
- if (this.running >= this.maxConcurrent) {
338
- return;
339
- }
340
- const work = this.queue.shift();
341
- if (!work) {
342
- this.checkIfEmptyAndNotify();
343
- return;
344
- }
345
- this.running++;
346
- try {
347
- await work();
348
- } catch (err) {
349
- } finally {
350
- this.running--;
351
- void this.doNextWork();
352
- }
353
- }
354
- async size() {
355
- return this.queue.length;
356
- }
357
- async waitUntilFinished() {
358
- return new Promise((resolve) => {
359
- if (this.queue.length === 0 && this.running === 0) {
360
- resolve();
361
- } else {
362
- this.emptyListeners.push(resolve);
363
- }
364
- });
365
- }
366
- checkIfEmptyAndNotify() {
367
- if (this.queue.length === 0 && this.running === 0) {
368
- while (this.emptyListeners.length) {
369
- const listener = this.emptyListeners.shift();
370
- if (listener) listener();
371
- }
372
- }
373
- }
374
- };
551
+ // src/managers/post.ts
552
+ import { createUniqueUuid, EventType } from "@elizaos/core";
375
553
 
376
554
  // src/common/callbacks.ts
377
555
  import { logger } from "@elizaos/core";
@@ -396,7 +574,7 @@ function standardCastHandlerCallback({
396
574
  return [];
397
575
  }
398
576
  const memories = [];
399
- for (let i = 0; i < casts.length; i++) {
577
+ for (let i = 0;i < casts.length; i++) {
400
578
  const cast = casts[i];
401
579
  logger.success(`[Farcaster] Published cast ${cast.hash}`);
402
580
  const memory = createCastMemory({
@@ -416,7 +594,7 @@ function standardCastHandlerCallback({
416
594
  }
417
595
  return memories;
418
596
  } catch (error) {
419
- logger.error("[Farcaster] Error posting cast:", error);
597
+ runtime.logger.error("[Farcaster] Error posting cast:", typeof error === "string" ? error : error.message);
420
598
  if (onError) {
421
599
  await onError(error);
422
600
  }
@@ -426,27 +604,18 @@ function standardCastHandlerCallback({
426
604
  return callback;
427
605
  }
428
606
 
429
- // src/common/prompts.ts
430
- var formatCast = (cast) => {
431
- return `ID: ${cast.hash}
432
- From: ${cast.profile.name} (@${cast.profile.username})${cast.profile.username})${cast.inReplyTo ? `
433
- In reply to: ${cast.inReplyTo.fid}` : ""}
434
- Text: ${cast.text}`;
435
- };
436
- var formatTimeline = (character, timeline) => `# ${character.name}'s Home Timeline
437
- ${timeline.map(formatCast).join("\n")}
438
- `;
439
-
440
- // src/managers/interactions.ts
441
- import { shouldRespondTemplate } from "@elizaos/core";
607
+ // src/managers/post.ts
608
+ init_constants();
442
609
 
443
610
  // src/common/types.ts
611
+ init_constants();
444
612
  import { z } from "zod";
445
613
  var FarcasterConfigSchema = z.object({
446
614
  FARCASTER_DRY_RUN: z.union([z.boolean(), z.string()]).transform((val) => typeof val === "string" ? val.toLowerCase() === "true" : val),
447
615
  FARCASTER_FID: z.number().int().min(1, "Farcaster fid is required"),
448
616
  MAX_CAST_LENGTH: z.number().int().default(DEFAULT_MAX_CAST_LENGTH),
449
617
  FARCASTER_POLL_INTERVAL: z.number().int().default(DEFAULT_POLL_INTERVAL),
618
+ FARCASTER_MODE: z.enum(["polling", "webhook"]).default("polling"),
450
619
  ENABLE_CAST: z.union([z.boolean(), z.string()]).transform((val) => typeof val === "string" ? val.toLowerCase() === "true" : val),
451
620
  CAST_INTERVAL_MIN: z.number().int(),
452
621
  CAST_INTERVAL_MAX: z.number().int(),
@@ -459,52 +628,356 @@ var FarcasterConfigSchema = z.object({
459
628
  FARCASTER_HUB_URL: z.string().min(1, "FARCASTER_HUB_URL is not set")
460
629
  });
461
630
 
462
- // src/managers/interactions.ts
463
- var FarcasterInteractionManager = class {
464
- timeout;
465
- isRunning = false;
631
+ // src/managers/post.ts
632
+ class FarcasterCastManager {
466
633
  client;
467
634
  runtime;
635
+ fid;
636
+ timeout;
468
637
  config;
469
- asyncQueue;
638
+ isRunning = false;
470
639
  constructor(opts) {
471
640
  this.client = opts.client;
472
641
  this.runtime = opts.runtime;
473
642
  this.config = opts.config;
474
- this.asyncQueue = new AsyncQueue(1);
643
+ this.fid = this.config.FARCASTER_FID;
644
+ }
645
+ async start() {
646
+ if (this.isRunning || !this.config.ENABLE_CAST) {
647
+ return;
648
+ }
649
+ this.isRunning = true;
650
+ this.runPeriodically();
651
+ }
652
+ async stop() {
653
+ if (this.timeout)
654
+ clearTimeout(this.timeout);
655
+ this.isRunning = false;
656
+ }
657
+ calculateDelay() {
658
+ const minMinutes = this.config.CAST_INTERVAL_MIN;
659
+ const maxMinutes = this.config.CAST_INTERVAL_MAX;
660
+ const randomMinutes = Math.floor(Math.random() * (maxMinutes - minMinutes + 1)) + minMinutes;
661
+ const delay = randomMinutes * 60 * 1000;
662
+ return { delay, randomMinutes };
663
+ }
664
+ async runPeriodically() {
665
+ if (this.config.CAST_IMMEDIATELY) {
666
+ await this.generateNewCast();
667
+ }
668
+ while (this.isRunning) {
669
+ try {
670
+ const lastPost = await this.runtime.getCache(lastCastCacheKey(this.fid));
671
+ const lastPostTimestamp = lastPost?.timestamp ?? 0;
672
+ const { delay, randomMinutes } = this.calculateDelay();
673
+ if (Date.now() > lastPostTimestamp + delay) {
674
+ await this.generateNewCast();
675
+ }
676
+ this.runtime.logger.log(`Next cast scheduled in ${randomMinutes} minutes`);
677
+ await new Promise((resolve) => this.timeout = setTimeout(resolve, delay));
678
+ } catch (error) {
679
+ this.runtime.logger.error({ agentId: this.runtime.agentId, error }, "[Farcaster] Error in periodic cast loop:");
680
+ }
681
+ }
682
+ }
683
+ async generateNewCast() {
684
+ this.runtime.logger.info("Generating new cast");
685
+ try {
686
+ const worldId = createUniqueUuid(this.runtime, this.fid.toString());
687
+ const roomId = createUniqueUuid(this.runtime, `${this.fid}-home`);
688
+ const callback = standardCastHandlerCallback({
689
+ client: this.client,
690
+ runtime: this.runtime,
691
+ config: this.config,
692
+ roomId,
693
+ onCompletion: async (casts, _memories) => {
694
+ const lastCast = casts[casts.length - 1];
695
+ await this.runtime.setCache(lastCastCacheKey(this.fid), {
696
+ hash: lastCast.hash,
697
+ timestamp: new Date(lastCast.timestamp).getTime()
698
+ });
699
+ }
700
+ });
701
+ this.runtime.emitEvent([EventType.POST_GENERATED, "FARCASTER_CAST_GENERATED" /* CAST_GENERATED */], {
702
+ runtime: this.runtime,
703
+ callback,
704
+ worldId,
705
+ userId: this.runtime.agentId,
706
+ roomId,
707
+ source: FARCASTER_SOURCE
708
+ });
709
+ } catch (error) {
710
+ this.runtime.logger.error({ error }, "[Farcaster] Error generating new cast");
711
+ }
712
+ }
713
+ }
714
+
715
+ // src/managers/interactions.ts
716
+ import {
717
+ ChannelType,
718
+ createUniqueUuid as createUniqueUuid2,
719
+ logger as logger3,
720
+ stringToUuid as stringToUuid2
721
+ } from "@elizaos/core";
722
+
723
+ // src/common/asyncqueue.ts
724
+ class AsyncQueue {
725
+ queue = [];
726
+ running = 0;
727
+ emptyListeners = [];
728
+ maxConcurrent;
729
+ constructor(maxConcurrent = 1) {
730
+ this.maxConcurrent = maxConcurrent;
731
+ }
732
+ async submit(work) {
733
+ return new Promise((resolve, reject) => {
734
+ this.queue.push(async () => {
735
+ try {
736
+ resolve(await work());
737
+ } catch (err) {
738
+ reject(err);
739
+ }
740
+ });
741
+ this.doNextWork();
742
+ });
743
+ }
744
+ async doNextWork() {
745
+ if (this.running >= this.maxConcurrent) {
746
+ return;
747
+ }
748
+ const work = this.queue.shift();
749
+ if (!work) {
750
+ this.checkIfEmptyAndNotify();
751
+ return;
752
+ }
753
+ this.running++;
754
+ try {
755
+ await work();
756
+ } catch (err) {} finally {
757
+ this.running--;
758
+ this.doNextWork();
759
+ }
760
+ }
761
+ async size() {
762
+ return this.queue.length;
475
763
  }
764
+ async waitUntilFinished() {
765
+ return new Promise((resolve) => {
766
+ if (this.queue.length === 0 && this.running === 0) {
767
+ resolve();
768
+ } else {
769
+ this.emptyListeners.push(resolve);
770
+ }
771
+ });
772
+ }
773
+ checkIfEmptyAndNotify() {
774
+ if (this.queue.length === 0 && this.running === 0) {
775
+ while (this.emptyListeners.length) {
776
+ const listener = this.emptyListeners.shift();
777
+ if (listener)
778
+ listener();
779
+ }
780
+ }
781
+ }
782
+ }
783
+
784
+ // src/managers/interactions.ts
785
+ init_constants();
786
+
787
+ // src/managers/interaction-source.ts
788
+ import { logger as logger2 } from "@elizaos/core";
789
+ class FarcasterInteractionSource {
790
+ client;
791
+ runtime;
792
+ config;
793
+ processor;
794
+ isRunning = false;
795
+ constructor(params) {
796
+ this.client = params.client;
797
+ this.runtime = params.runtime;
798
+ this.config = params.config;
799
+ this.processor = params.processor;
800
+ }
801
+ }
802
+
803
+ class FarcasterPollingSource extends FarcasterInteractionSource {
804
+ timeout;
476
805
  async start() {
477
- logger2.info("Starting Farcaster interactions");
806
+ logger2.info("Starting Farcaster polling mode");
478
807
  if (this.isRunning) {
479
808
  return;
480
809
  }
481
810
  this.isRunning = true;
482
- void this.runPeriodically();
811
+ this.runPeriodically();
483
812
  }
484
813
  async stop() {
485
- if (this.timeout) clearTimeout(this.timeout);
814
+ logger2.info("Stopping Farcaster polling mode");
815
+ if (this.timeout)
816
+ clearTimeout(this.timeout);
486
817
  this.isRunning = false;
487
818
  }
488
819
  async runPeriodically() {
489
820
  while (this.isRunning) {
490
821
  try {
491
- await this.handleInteractions();
492
- const delay = this.config.FARCASTER_POLL_INTERVAL * 1e3;
493
- await new Promise((resolve) => this.timeout = setTimeout(resolve, delay));
822
+ await this.pollForInteractions();
823
+ const delay = this.config.FARCASTER_POLL_INTERVAL * 1000;
824
+ await new Promise((resolve) => this.timeout = setTimeout(resolve, delay));
825
+ } catch (error) {
826
+ this.runtime.logger.error({ error }, "[Farcaster] Error in polling:");
827
+ }
828
+ }
829
+ }
830
+ async pollForInteractions() {
831
+ const agentFid = this.config.FARCASTER_FID;
832
+ const mentions = await this.client.getMentions({
833
+ fid: agentFid,
834
+ pageSize: 20
835
+ });
836
+ for (const cast of mentions) {
837
+ try {
838
+ const mention = neynarCastToCast(cast);
839
+ const memoryId = castUuid({ agentId: this.runtime.agentId, hash: mention.hash });
840
+ if (await this.runtime.getMemoryById(memoryId)) {
841
+ continue;
842
+ }
843
+ this.runtime.logger.info({ hash: mention.hash }, "New Cast found");
844
+ if (mention.authorFid === agentFid) {
845
+ const memory = await this.processor.ensureCastConnection(mention);
846
+ await this.runtime.addEmbeddingToMemory(memory);
847
+ await this.runtime.createMemory(memory, "messages");
848
+ continue;
849
+ }
850
+ await this.processor.processMention(cast);
851
+ } catch (error) {
852
+ this.runtime.logger.error({ error }, "[Farcaster] Error processing mention:");
853
+ }
854
+ }
855
+ }
856
+ }
857
+
858
+ class FarcasterWebhookSource extends FarcasterInteractionSource {
859
+ async start() {
860
+ logger2.info("Starting Farcaster webhook mode");
861
+ if (this.isRunning) {
862
+ return;
863
+ }
864
+ this.isRunning = true;
865
+ logger2.info("Webhook source is active - waiting for webhook events");
866
+ }
867
+ async stop() {
868
+ logger2.info("Stopping Farcaster webhook mode");
869
+ this.isRunning = false;
870
+ }
871
+ async processWebhookData(webhookData) {
872
+ if (!this.isRunning) {
873
+ logger2.warn("Webhook source is not running, ignoring webhook data");
874
+ return;
875
+ }
876
+ try {
877
+ await this.processor.processWebhookData(webhookData);
878
+ } catch (error) {
879
+ this.runtime.logger.error({ error }, "[Farcaster] Error processing webhook data:");
880
+ }
881
+ }
882
+ }
883
+ function createFarcasterInteractionSource(params) {
884
+ const mode = params.config.FARCASTER_MODE;
885
+ switch (mode) {
886
+ case "webhook":
887
+ return new FarcasterWebhookSource(params);
888
+ case "polling":
889
+ default:
890
+ return new FarcasterPollingSource(params);
891
+ }
892
+ }
893
+
894
+ // src/managers/interactions.ts
895
+ class FarcasterInteractionManager {
896
+ client;
897
+ runtime;
898
+ config;
899
+ asyncQueue;
900
+ mode;
901
+ source;
902
+ constructor(opts) {
903
+ this.client = opts.client;
904
+ this.runtime = opts.runtime;
905
+ this.config = opts.config;
906
+ this.asyncQueue = new AsyncQueue(1);
907
+ this.mode = opts.config.FARCASTER_MODE;
908
+ this.source = createFarcasterInteractionSource({
909
+ client: this.client,
910
+ runtime: this.runtime,
911
+ config: this.config,
912
+ processor: this
913
+ });
914
+ logger3.info(`Farcaster interaction mode: ${this.mode}`);
915
+ }
916
+ async processMention(cast) {
917
+ const agentFid = this.config.FARCASTER_FID;
918
+ const agent = await this.client.getProfile(agentFid);
919
+ const mention = neynarCastToCast(cast);
920
+ await this.handleMentionCast({ agent, mention, cast });
921
+ }
922
+ async processReply(cast) {
923
+ const agentFid = this.config.FARCASTER_FID;
924
+ const agent = await this.client.getProfile(agentFid);
925
+ const reply = neynarCastToCast(cast);
926
+ await this.handleMentionCast({ agent, mention: reply, cast });
927
+ }
928
+ async processWebhookData(webhookData) {
929
+ if (webhookData.type !== "cast.created" || !webhookData.data) {
930
+ logger3.debug("Ignoring non-cast webhook event:", webhookData.type);
931
+ return;
932
+ }
933
+ const castData = webhookData.data;
934
+ const agentFid = this.config.FARCASTER_FID;
935
+ if (!castData.author || !castData.hash || typeof castData.author.fid !== "number") {
936
+ logger3.warn("Invalid webhook cast data structure - missing author, hash, or author.fid");
937
+ return;
938
+ }
939
+ if (castData.author.fid === agentFid) {
940
+ logger3.debug("Skipping webhook event from agent itself");
941
+ return;
942
+ }
943
+ const memoryId = castUuid({ agentId: this.runtime.agentId, hash: castData.hash });
944
+ if (await this.runtime.getMemoryById(memoryId)) {
945
+ logger3.debug("Skipping already processed webhook cast:", castData.hash);
946
+ return;
947
+ }
948
+ const isMention = castData.mentioned_profiles?.some((profile) => profile.fid === agentFid);
949
+ const isReply = castData.parent_hash && castData.parent_author?.fid === agentFid;
950
+ if (isMention) {
951
+ const username = castData.author.username || "unknown";
952
+ const text = castData.text || "";
953
+ logger3.info(`Processing webhook MENTION from @${username}: "${text}"`);
954
+ try {
955
+ const neynarCast = await this.client.getCast(castData.hash);
956
+ await this.processMention(neynarCast);
957
+ } catch (error) {
958
+ logger3.error({ agentId: this.runtime.agentId, error }, "Failed to process webhook mention from @" + username);
959
+ }
960
+ } else if (isReply) {
961
+ const username = castData.author.username || "unknown";
962
+ const text = castData.text || "";
963
+ logger3.info(`Processing webhook REPLY from @${username}: "${text}"`);
964
+ try {
965
+ const neynarCast = await this.client.getCast(castData.hash);
966
+ await this.processReply(neynarCast);
494
967
  } catch (error) {
495
- logger2.error("[Farcaster] Error in periodic interactions:", this.runtime.agentId, error);
968
+ this.runtime.logger.error({ error }, `Failed to process webhook reply from @${username}:`);
496
969
  }
970
+ } else {
971
+ logger3.debug("Webhook cast is neither mention nor reply to agent");
497
972
  }
498
973
  }
499
974
  async ensureCastConnection(cast) {
500
975
  return await this.asyncQueue.submit(async () => {
501
- var _a, _b;
502
976
  const memoryId = castUuid({ agentId: this.runtime.agentId, hash: cast.hash });
503
- const conversationId = cast.threadId ?? ((_a = cast.inReplyTo) == null ? void 0 : _a.hash) ?? cast.hash;
504
- const entityId = createUniqueUuid(this.runtime, cast.authorFid.toString());
505
- const worldId = createUniqueUuid(this.runtime, cast.authorFid.toString());
506
- const serverId = cast.authorFid.toString();
507
- const roomId = createUniqueUuid(this.runtime, conversationId);
977
+ const conversationId = cast.threadId ?? cast.inReplyTo?.hash ?? cast.hash;
978
+ const entityId = createUniqueUuid2(this.runtime, cast.authorFid.toString());
979
+ const worldId = createUniqueUuid2(this.runtime, cast.authorFid.toString());
980
+ const roomId = createUniqueUuid2(this.runtime, conversationId);
508
981
  if (entityId !== this.runtime.agentId) {
509
982
  await this.runtime.ensureConnection({
510
983
  entityId,
@@ -515,7 +988,7 @@ var FarcasterInteractionManager = class {
515
988
  source: FARCASTER_SOURCE,
516
989
  type: ChannelType.THREAD,
517
990
  channelId: conversationId,
518
- serverId,
991
+ messageServerId: stringToUuid2(cast.authorFid.toString()),
519
992
  worldId,
520
993
  metadata: {
521
994
  ownership: { ownerId: cast.authorFid.toString() },
@@ -532,8 +1005,7 @@ var FarcasterInteractionManager = class {
532
1005
  agentId: this.runtime.agentId,
533
1006
  content: {
534
1007
  text: cast.text,
535
- // need to pull imageUrls
536
- inReplyTo: ((_b = cast.inReplyTo) == null ? void 0 : _b.hash) ? castUuid({ agentId: this.runtime.agentId, hash: cast.inReplyTo.hash }) : void 0,
1008
+ inReplyTo: cast.inReplyTo?.hash ? castUuid({ agentId: this.runtime.agentId, hash: cast.inReplyTo.hash }) : undefined,
537
1009
  source: FARCASTER_SOURCE,
538
1010
  channelType: ChannelType.THREAD
539
1011
  },
@@ -544,34 +1016,9 @@ var FarcasterInteractionManager = class {
544
1016
  return memory;
545
1017
  });
546
1018
  }
547
- async handleInteractions() {
548
- const agentFid = this.config.FARCASTER_FID;
549
- const [mentions, agent] = await Promise.all([
550
- this.client.getMentions({
551
- fid: agentFid,
552
- pageSize: 20
553
- }),
554
- this.client.getProfile(agentFid)
555
- ]);
556
- for (const cast of mentions) {
557
- const mention = neynarCastToCast(cast);
558
- const memoryId = castUuid({ agentId: this.runtime.agentId, hash: mention.hash });
559
- if (await this.runtime.getMemoryById(memoryId)) {
560
- continue;
561
- }
562
- logger2.info("New Cast found", mention.hash);
563
- if (mention.authorFid === agentFid) {
564
- const memory = await this.ensureCastConnection(mention);
565
- await this.runtime.addEmbeddingToMemory(memory);
566
- await this.runtime.createMemory(memory, "messages");
567
- continue;
568
- }
569
- await this.handleMentionCast({ agent, mention, cast });
570
- }
571
- }
572
1019
  async buildThreadForCast(cast, skipMemoryId) {
573
1020
  const thread = [];
574
- const visited = /* @__PURE__ */ new Set();
1021
+ const visited = new Set;
575
1022
  const client = this.client;
576
1023
  const runtime = this.runtime;
577
1024
  const self = this;
@@ -583,12 +1030,12 @@ var FarcasterInteractionManager = class {
583
1030
  visited.add(currentCast.hash);
584
1031
  const memory = await runtime.getMemoryById(memoryId);
585
1032
  if (!memory) {
586
- logger2.info("Creating memory for cast", currentCast.hash);
587
- const memory2 = await self.ensureCastConnection(currentCast);
588
- await runtime.createMemory(memory2, "messages");
1033
+ logger3.info({ hash: currentCast.hash }, "Creating memory for cast");
1034
+ const newMemory = await self.ensureCastConnection(currentCast);
1035
+ await runtime.createMemory(newMemory, "messages");
589
1036
  runtime.emitEvent("FARCASTER_THREAD_CAST_CREATED" /* THREAD_CAST_CREATED */, {
590
1037
  runtime,
591
- memory: memory2,
1038
+ memory: newMemory,
592
1039
  cast: currentCast,
593
1040
  source: FARCASTER_SOURCE
594
1041
  });
@@ -607,51 +1054,14 @@ var FarcasterInteractionManager = class {
607
1054
  mention,
608
1055
  cast
609
1056
  }) {
610
- var _a, _b, _c;
611
1057
  if (mention.profile.fid === agent.fid) {
612
- logger2.info("skipping cast from bot itself", mention.hash);
1058
+ logger3.info({ hash: mention.hash }, "skipping cast from bot itself");
613
1059
  return;
614
1060
  }
615
1061
  const memory = await this.ensureCastConnection(mention);
616
- const thread = await this.buildThreadForCast(
617
- mention,
618
- memory.id ? /* @__PURE__ */ new Set([memory.id]) : /* @__PURE__ */ new Set()
619
- );
1062
+ const thread = await this.buildThreadForCast(mention, memory.id ? new Set([memory.id]) : new Set);
620
1063
  if (!memory.content.text || memory.content.text.trim() === "") {
621
- logger2.info("skipping cast with no text", mention.hash);
622
- return;
623
- }
624
- const currentPost = formatCast(mention);
625
- const { timeline } = await this.client.getTimeline({ fid: agent.fid, pageSize: 20 });
626
- const formattedTimeline = formatTimeline(this.runtime.character, timeline);
627
- const formattedConversation = thread.map(
628
- (c) => `
629
- - @${c.profile.username} (${formatCastTimestamp(c.timestamp)}):
630
- ${c.text}`.trim()
631
- ).join("\n\n");
632
- const state = await this.runtime.composeState(memory);
633
- state.values = {
634
- ...state.values,
635
- farcasterUsername: agent.username,
636
- timeline: formattedTimeline,
637
- currentPost,
638
- formattedConversation
639
- };
640
- const shouldRespondPrompt = composePrompt({
641
- state,
642
- template: ((_a = this.runtime.character.templates) == null ? void 0 : _a.farcasterShouldRespondTemplate) || ((_c = (_b = this.runtime.character) == null ? void 0 : _b.templates) == null ? void 0 : _c.shouldRespondTemplate) || shouldRespondTemplate
643
- });
644
- const response = await this.runtime.useModel(ModelType.TEXT_SMALL, {
645
- prompt: shouldRespondPrompt
646
- });
647
- const responseActions = (response.match(/(?:RESPOND|IGNORE|STOP)/g) || ["IGNORE"])[0];
648
- if (responseActions !== "RESPOND") {
649
- logger2.info(`Not responding to cast based on shouldRespond decision: ${responseActions}`);
650
- try {
651
- await this.runtime.createMemory(memory, "messages");
652
- } catch (error) {
653
- logger2.error("Error creating ignoredmemory", error);
654
- }
1064
+ logger3.info({ hash: mention.hash }, "skipping cast with no text");
655
1065
  return;
656
1066
  }
657
1067
  const callback = standardCastHandlerCallback({
@@ -664,113 +1074,39 @@ var FarcasterInteractionManager = class {
664
1074
  fid: mention.authorFid
665
1075
  }
666
1076
  });
667
- const messageReceivedPayload = {
668
- runtime: this.runtime,
669
- message: memory,
670
- source: FARCASTER_SOURCE,
671
- callback
672
- };
673
- this.runtime.emitEvent(EventType.MESSAGE_RECEIVED, messageReceivedPayload);
1077
+ try {
1078
+ if (!this.runtime.messageService) {
1079
+ logger3.warn("[Farcaster] messageService not available, skipping mention handling");
1080
+ return;
1081
+ }
1082
+ await this.runtime.messageService.handleMessage(this.runtime, memory, callback);
1083
+ } catch (error) {
1084
+ logger3.error({
1085
+ error: error instanceof Error ? error.message : String(error),
1086
+ castHash: mention.hash
1087
+ }, "[Farcaster] Error processing mention");
1088
+ }
674
1089
  const mentionPayload = {
675
1090
  runtime: this.runtime,
676
1091
  memory,
677
1092
  cast,
678
1093
  source: FARCASTER_SOURCE,
679
- callback: async (ontent, _files) => {
680
- logger2.info("[Farcaster] mention received response:", response);
681
- return [];
682
- }
1094
+ callback
683
1095
  };
684
1096
  this.runtime.emitEvent("FARCASTER_MENTION_RECEIVED" /* MENTION_RECEIVED */, mentionPayload);
685
1097
  }
686
- };
687
-
688
- // src/managers/post.ts
689
- import { createUniqueUuid as createUniqueUuid2, EventType as EventType2, logger as logger3 } from "@elizaos/core";
690
- var FarcasterCastManager = class {
691
- client;
692
- runtime;
693
- fid;
694
- timeout;
695
- config;
696
- isRunning = false;
697
- constructor(opts) {
698
- this.client = opts.client;
699
- this.runtime = opts.runtime;
700
- this.config = opts.config;
701
- this.fid = this.config.FARCASTER_FID;
702
- }
703
1098
  async start() {
704
- if (this.isRunning || !this.config.ENABLE_CAST) {
705
- return;
706
- }
707
- this.isRunning = true;
708
- void this.runPeriodically();
1099
+ logger3.info(`Starting Farcaster interaction manager in ${this.mode} mode`);
1100
+ await this.source.start();
709
1101
  }
710
1102
  async stop() {
711
- if (this.timeout) clearTimeout(this.timeout);
712
- this.isRunning = false;
713
- }
714
- calculateDelay() {
715
- const minMinutes = this.config.CAST_INTERVAL_MIN;
716
- const maxMinutes = this.config.CAST_INTERVAL_MAX;
717
- const randomMinutes = Math.floor(Math.random() * (maxMinutes - minMinutes + 1)) + minMinutes;
718
- const delay = randomMinutes * 60 * 1e3;
719
- return { delay, randomMinutes };
720
- }
721
- async runPeriodically() {
722
- if (this.config.CAST_IMMEDIATELY) {
723
- await this.generateNewCast();
724
- }
725
- while (this.isRunning) {
726
- try {
727
- const lastPost = await this.runtime.getCache(lastCastCacheKey(this.fid));
728
- const lastPostTimestamp = (lastPost == null ? void 0 : lastPost.timestamp) ?? 0;
729
- const { delay, randomMinutes } = this.calculateDelay();
730
- if (Date.now() > lastPostTimestamp + delay) {
731
- await this.generateNewCast();
732
- }
733
- logger3.log(`Next cast scheduled in ${randomMinutes} minutes`);
734
- await new Promise((resolve) => this.timeout = setTimeout(resolve, delay));
735
- } catch (error) {
736
- logger3.error("[Farcaster] Error in periodic cast loop:", this.runtime.agentId, error);
737
- }
738
- }
739
- }
740
- async generateNewCast() {
741
- logger3.info("Generating new cast");
742
- try {
743
- const worldId = createUniqueUuid2(this.runtime, this.fid.toString());
744
- const roomId = createUniqueUuid2(this.runtime, `${this.fid}-home`);
745
- const callback = standardCastHandlerCallback({
746
- client: this.client,
747
- runtime: this.runtime,
748
- config: this.config,
749
- roomId,
750
- onCompletion: async (casts, _memories) => {
751
- const lastCast = casts[casts.length - 1];
752
- await this.runtime.setCache(lastCastCacheKey(this.fid), {
753
- hash: lastCast.hash,
754
- timestamp: new Date(lastCast.timestamp).getTime()
755
- });
756
- }
757
- });
758
- this.runtime.emitEvent([EventType2.POST_GENERATED, "FARCASTER_CAST_GENERATED" /* CAST_GENERATED */], {
759
- runtime: this.runtime,
760
- callback,
761
- worldId,
762
- userId: this.runtime.agentId,
763
- roomId,
764
- source: FARCASTER_SOURCE
765
- });
766
- } catch (error) {
767
- logger3.error("Error generating new cast:", error);
768
- }
1103
+ logger3.info("Stopping Farcaster interaction manager");
1104
+ await this.source.stop();
769
1105
  }
770
- };
1106
+ }
771
1107
 
772
1108
  // src/managers/agent.ts
773
- var FarcasterAgentManager = class {
1109
+ class FarcasterAgentManager {
774
1110
  runtime;
775
1111
  client;
776
1112
  casts;
@@ -783,8 +1119,8 @@ var FarcasterAgentManager = class {
783
1119
  const client = new FarcasterClient({ neynar, signerUuid });
784
1120
  this.client = client;
785
1121
  logger4.success("Farcaster Neynar client initialized.");
786
- this.casts = new FarcasterCastManager({ client, runtime, config });
787
1122
  this.interactions = new FarcasterInteractionManager({ client, runtime, config });
1123
+ this.casts = new FarcasterCastManager({ client, runtime, config });
788
1124
  }
789
1125
  async start() {
790
1126
  await Promise.all([this.casts.start(), this.interactions.start()]);
@@ -792,13 +1128,15 @@ var FarcasterAgentManager = class {
792
1128
  async stop() {
793
1129
  await Promise.all([this.casts.stop(), this.interactions.stop()]);
794
1130
  }
795
- };
1131
+ }
796
1132
 
797
1133
  // src/common/config.ts
1134
+ init_constants();
798
1135
  import { logger as logger5, parseBooleanFromText } from "@elizaos/core";
799
1136
  import { ZodError } from "zod";
800
1137
  function safeParseInt(value, defaultValue) {
801
- if (!value) return defaultValue;
1138
+ if (!value)
1139
+ return defaultValue;
802
1140
  const parsed = Number.parseInt(value, 10);
803
1141
  return Number.isNaN(parsed) ? defaultValue : Math.max(1, parsed);
804
1142
  }
@@ -813,38 +1151,20 @@ function validateFarcasterConfig(runtime) {
813
1151
  try {
814
1152
  const farcasterConfig = {
815
1153
  FARCASTER_DRY_RUN: runtime.getSetting("FARCASTER_DRY_RUN") || parseBooleanFromText(process.env.FARCASTER_DRY_RUN || "false"),
816
- FARCASTER_FID: Number.isNaN(fid) ? void 0 : fid,
817
- MAX_CAST_LENGTH: safeParseInt(
818
- runtime.getSetting("MAX_CAST_LENGTH") || process.env.MAX_CAST_LENGTH,
819
- DEFAULT_MAX_CAST_LENGTH
820
- ),
821
- FARCASTER_POLL_INTERVAL: safeParseInt(
822
- runtime.getSetting("FARCASTER_POLL_INTERVAL") || process.env.FARCASTER_POLL_INTERVAL,
823
- DEFAULT_POLL_INTERVAL
824
- ),
1154
+ FARCASTER_FID: Number.isNaN(fid) ? undefined : fid,
1155
+ MAX_CAST_LENGTH: safeParseInt(runtime.getSetting("MAX_CAST_LENGTH") || process.env.MAX_CAST_LENGTH, DEFAULT_MAX_CAST_LENGTH),
1156
+ FARCASTER_POLL_INTERVAL: safeParseInt(runtime.getSetting("FARCASTER_POLL_INTERVAL") || process.env.FARCASTER_POLL_INTERVAL, DEFAULT_POLL_INTERVAL),
825
1157
  ENABLE_CAST: runtime.getSetting("ENABLE_CAST") || parseBooleanFromText(process.env.ENABLE_CAST || "true"),
826
- CAST_INTERVAL_MIN: safeParseInt(
827
- runtime.getSetting("CAST_INTERVAL_MIN") || process.env.CAST_INTERVAL_MIN,
828
- DEFAULT_CAST_INTERVAL_MIN
829
- ),
830
- CAST_INTERVAL_MAX: safeParseInt(
831
- runtime.getSetting("CAST_INTERVAL_MAX") || process.env.CAST_INTERVAL_MAX,
832
- DEFAULT_CAST_INTERVAL_MAX
833
- ),
1158
+ CAST_INTERVAL_MIN: safeParseInt(runtime.getSetting("CAST_INTERVAL_MIN") || process.env.CAST_INTERVAL_MIN, DEFAULT_CAST_INTERVAL_MIN),
1159
+ CAST_INTERVAL_MAX: safeParseInt(runtime.getSetting("CAST_INTERVAL_MAX") || process.env.CAST_INTERVAL_MAX, DEFAULT_CAST_INTERVAL_MAX),
834
1160
  ENABLE_ACTION_PROCESSING: runtime.getSetting("ENABLE_ACTION_PROCESSING") || parseBooleanFromText(process.env.ENABLE_ACTION_PROCESSING || "false"),
835
- ACTION_INTERVAL: safeParseInt(
836
- runtime.getSetting("ACTION_INTERVAL") || process.env.ACTION_INTERVAL,
837
- 5
838
- ),
839
- // 5 minutes
1161
+ ACTION_INTERVAL: safeParseInt(runtime.getSetting("ACTION_INTERVAL") || process.env.ACTION_INTERVAL, 5),
840
1162
  CAST_IMMEDIATELY: runtime.getSetting("CAST_IMMEDIATELY") || parseBooleanFromText(process.env.CAST_IMMEDIATELY || "false"),
841
- MAX_ACTIONS_PROCESSING: safeParseInt(
842
- runtime.getSetting("MAX_ACTIONS_PROCESSING") || process.env.MAX_ACTIONS_PROCESSING,
843
- 1
844
- ),
1163
+ MAX_ACTIONS_PROCESSING: safeParseInt(runtime.getSetting("MAX_ACTIONS_PROCESSING") || process.env.MAX_ACTIONS_PROCESSING, 1),
845
1164
  FARCASTER_SIGNER_UUID: runtime.getSetting("FARCASTER_SIGNER_UUID") || process.env.FARCASTER_SIGNER_UUID,
846
1165
  FARCASTER_NEYNAR_API_KEY: runtime.getSetting("FARCASTER_NEYNAR_API_KEY") || process.env.FARCASTER_NEYNAR_API_KEY,
847
- FARCASTER_HUB_URL: runtime.getSetting("FARCASTER_HUB_URL") || process.env.FARCASTER_HUB_URL || "hub.pinata.cloud"
1166
+ FARCASTER_HUB_URL: runtime.getSetting("FARCASTER_HUB_URL") || process.env.FARCASTER_HUB_URL || "hub.pinata.cloud",
1167
+ FARCASTER_MODE: runtime.getSetting("FARCASTER_MODE") || process.env.FARCASTER_MODE || "polling"
848
1168
  };
849
1169
  const config = FarcasterConfigSchema.parse(farcasterConfig);
850
1170
  const isDryRun = config.FARCASTER_DRY_RUN;
@@ -853,9 +1173,7 @@ function validateFarcasterConfig(runtime) {
853
1173
  logger5.log(`- Dry Run Mode: ${isDryRun ? "enabled" : "disabled"}`);
854
1174
  logger5.log(`- Enable Cast: ${config.ENABLE_CAST ? "enabled" : "disabled"}`);
855
1175
  if (config.ENABLE_CAST) {
856
- logger5.log(
857
- `- Cast Interval: ${config.CAST_INTERVAL_MIN}-${config.CAST_INTERVAL_MAX} minutes`
858
- );
1176
+ logger5.log(`- Cast Interval: ${config.CAST_INTERVAL_MIN}-${config.CAST_INTERVAL_MAX} minutes`);
859
1177
  logger5.log(`- Cast Immediately: ${config.CAST_IMMEDIATELY ? "enabled" : "disabled"}`);
860
1178
  }
861
1179
  logger5.log(`- Action Processing: ${config.ENABLE_ACTION_PROCESSING ? "enabled" : "disabled"}`);
@@ -866,7 +1184,8 @@ function validateFarcasterConfig(runtime) {
866
1184
  return config;
867
1185
  } catch (error) {
868
1186
  if (error instanceof ZodError) {
869
- const errorMessages = error.errors.map((err) => `${err.path.join(".")}: ${err.message}`).join("\n");
1187
+ const errorMessages = error.issues.map((err) => `${err.path.join(".")}: ${err.message}`).join(`
1188
+ `);
870
1189
  throw new Error(`Farcaster configuration validation failed:
871
1190
  ${errorMessages}`);
872
1191
  }
@@ -875,64 +1194,74 @@ ${errorMessages}`);
875
1194
  }
876
1195
 
877
1196
  // src/services/MessageService.ts
878
- import {
879
- logger as logger6,
880
- createUniqueUuid as createUniqueUuid3
881
- } from "@elizaos/core";
882
- var FarcasterMessageService = class {
1197
+ import { createUniqueUuid as createUniqueUuid3 } from "@elizaos/core";
1198
+ init_constants();
1199
+ class FarcasterMessageService {
1200
+ client;
1201
+ runtime;
883
1202
  constructor(client, runtime) {
884
1203
  this.client = client;
885
1204
  this.runtime = runtime;
886
1205
  }
1206
+ castToMessage(cast, agentId, extraMetadata) {
1207
+ return {
1208
+ id: castUuid({ hash: cast.hash, agentId }),
1209
+ agentId,
1210
+ roomId: createUniqueUuid3(this.runtime, cast.threadId || cast.hash),
1211
+ userId: cast.profile.fid.toString(),
1212
+ username: cast.profile.username,
1213
+ text: cast.text,
1214
+ type: cast.inReplyTo ? "REPLY" /* REPLY */ : "CAST" /* CAST */,
1215
+ timestamp: cast.timestamp.getTime(),
1216
+ inReplyTo: cast.inReplyTo ? castUuid({ hash: cast.inReplyTo.hash, agentId }) : undefined,
1217
+ metadata: {
1218
+ source: FARCASTER_SOURCE,
1219
+ castHash: cast.hash,
1220
+ threadId: cast.threadId,
1221
+ authorFid: cast.authorFid,
1222
+ ...extraMetadata || {}
1223
+ }
1224
+ };
1225
+ }
887
1226
  async getMessages(options) {
888
1227
  try {
889
- const { roomId, limit = 20 } = options;
1228
+ const { agentId, roomId, limit = 20 } = options;
1229
+ const fidStr = this.runtime.getSetting("FARCASTER_FID");
1230
+ const fid = fidStr ? parseInt(fidStr, 10) : NaN;
1231
+ if (!fid || isNaN(fid)) {
1232
+ this.runtime.logger.error("[Farcaster] FARCASTER_FID is not configured");
1233
+ return [];
1234
+ }
890
1235
  const { timeline } = await this.client.getTimeline({
891
- fid: parseInt(
892
- this.runtime.getSetting("FARCASTER_FID") || this.runtime.config.FARCASTER_FID
893
- ),
1236
+ fid,
894
1237
  pageSize: limit
895
1238
  });
896
- const messages = timeline.filter((cast) => {
1239
+ const messages = timeline.map((cast) => this.castToMessage(cast, agentId)).filter((message) => {
897
1240
  if (roomId) {
898
- const castRoomId = createUniqueUuid3(this.runtime, cast.threadId || cast.hash);
899
- return castRoomId === roomId;
1241
+ return message.roomId === roomId;
900
1242
  }
901
1243
  return true;
902
- }).map((cast) => ({
903
- id: castUuid({ hash: cast.hash, agentId: this.runtime.agentId }),
904
- agentId: this.runtime.agentId,
905
- roomId: createUniqueUuid3(this.runtime, cast.threadId || cast.hash),
906
- userId: cast.profile.fid.toString(),
907
- username: cast.profile.username,
908
- text: cast.text,
909
- type: cast.inReplyTo ? "REPLY" /* REPLY */ : "CAST" /* CAST */,
910
- timestamp: cast.timestamp.getTime(),
911
- inReplyTo: cast.inReplyTo ? castUuid({ hash: cast.inReplyTo.hash, agentId: this.runtime.agentId }) : void 0,
912
- metadata: {
913
- castHash: cast.hash,
914
- threadId: cast.threadId,
915
- authorFid: cast.authorFid
916
- }
917
- }));
1244
+ });
918
1245
  return messages;
919
1246
  } catch (error) {
920
- logger6.error("[Farcaster] Error fetching messages:", error);
1247
+ this.runtime.logger.error({ error }, "[Farcaster] Error fetching messages");
921
1248
  return [];
922
1249
  }
923
1250
  }
924
1251
  async sendMessage(options) {
925
- var _a;
926
1252
  try {
927
1253
  const { text, type, roomId, replyToId, agentId } = options;
928
- let inReplyTo = void 0;
1254
+ let inReplyTo = undefined;
929
1255
  if (replyToId && type === "REPLY" /* REPLY */) {
930
- const parentHash = ((_a = options.metadata) == null ? void 0 : _a.parentHash) || replyToId;
1256
+ const parentHash = options.metadata?.parentHash || replyToId;
1257
+ const fidStr = this.runtime.getSetting("FARCASTER_FID");
1258
+ const fid = fidStr ? parseInt(fidStr, 10) : NaN;
1259
+ if (!fid || isNaN(fid)) {
1260
+ throw new Error("FARCASTER_FID is not configured");
1261
+ }
931
1262
  inReplyTo = {
932
1263
  hash: parentHash,
933
- fid: parseInt(
934
- this.runtime.getSetting("FARCASTER_FID") || this.runtime.config.FARCASTER_FID
935
- )
1264
+ fid
936
1265
  };
937
1266
  }
938
1267
  const casts = await this.client.sendCast({
@@ -943,23 +1272,9 @@ var FarcasterMessageService = class {
943
1272
  throw new Error("No cast was created");
944
1273
  }
945
1274
  const cast = neynarCastToCast(casts[0]);
946
- const message = {
947
- id: castUuid({ hash: cast.hash, agentId }),
948
- agentId,
949
- roomId,
950
- userId: cast.profile.fid.toString(),
951
- username: cast.profile.username,
952
- text: cast.text,
953
- type,
954
- timestamp: cast.timestamp.getTime(),
955
- inReplyTo: inReplyTo ? castUuid({ hash: inReplyTo.hash, agentId }) : void 0,
956
- metadata: {
957
- ...options.metadata,
958
- castHash: cast.hash,
959
- threadId: cast.threadId,
960
- authorFid: cast.authorFid
961
- }
962
- };
1275
+ const message = this.castToMessage(cast, agentId, options.metadata);
1276
+ message.roomId = roomId;
1277
+ message.type = type;
963
1278
  await this.runtime.emitEvent("FARCASTER_CAST_GENERATED" /* CAST_GENERATED */, {
964
1279
  runtime: this.runtime,
965
1280
  castHash: cast.hash,
@@ -968,78 +1283,84 @@ var FarcasterMessageService = class {
968
1283
  });
969
1284
  return message;
970
1285
  } catch (error) {
971
- logger6.error("[Farcaster] Error sending message:", error);
1286
+ this.runtime.logger.error({ error }, "[Farcaster] Error sending message");
972
1287
  throw error;
973
1288
  }
974
1289
  }
975
1290
  async deleteMessage(messageId, agentId) {
976
- logger6.warn("[Farcaster] Cast deletion is not supported by the Farcaster API");
1291
+ this.runtime.logger.warn("[Farcaster] Cast deletion is not supported by the Farcaster API");
977
1292
  }
978
1293
  async getMessage(messageId, agentId) {
979
1294
  try {
980
1295
  const castHash = messageId;
981
1296
  const cast = await this.client.getCast(castHash);
982
1297
  const farcasterCast = neynarCastToCast(cast);
983
- const message = {
984
- id: castUuid({ hash: farcasterCast.hash, agentId }),
985
- agentId,
986
- roomId: createUniqueUuid3(this.runtime, farcasterCast.threadId || farcasterCast.hash),
987
- userId: farcasterCast.profile.fid.toString(),
988
- username: farcasterCast.profile.username,
989
- text: farcasterCast.text,
990
- type: farcasterCast.inReplyTo ? "REPLY" /* REPLY */ : "CAST" /* CAST */,
991
- timestamp: farcasterCast.timestamp.getTime(),
992
- inReplyTo: farcasterCast.inReplyTo ? castUuid({ hash: farcasterCast.inReplyTo.hash, agentId }) : void 0,
993
- metadata: {
994
- castHash: farcasterCast.hash,
995
- threadId: farcasterCast.threadId,
996
- authorFid: farcasterCast.authorFid
997
- }
998
- };
999
- return message;
1298
+ return this.castToMessage(farcasterCast, agentId);
1000
1299
  } catch (error) {
1001
- logger6.error("[Farcaster] Error fetching message:", error);
1300
+ this.runtime.logger.error({ error }, "[Farcaster] Error fetching message");
1002
1301
  return null;
1003
1302
  }
1004
1303
  }
1304
+ async getThread(params) {
1305
+ try {
1306
+ const thread = [];
1307
+ const visited = new Set;
1308
+ let currentHash = params.castHash;
1309
+ while (currentHash) {
1310
+ if (visited.has(currentHash)) {
1311
+ break;
1312
+ }
1313
+ visited.add(currentHash);
1314
+ const cast = neynarCastToCast(await this.client.getCast(currentHash));
1315
+ thread.unshift(this.castToMessage(cast, params.agentId));
1316
+ currentHash = cast.inReplyTo?.hash;
1317
+ }
1318
+ return thread;
1319
+ } catch (error) {
1320
+ this.runtime.logger.error({ error }, "[Farcaster] Error fetching thread");
1321
+ return [];
1322
+ }
1323
+ }
1005
1324
  async markAsRead(messageIds, agentId) {
1006
- logger6.debug("[Farcaster] Mark as read is not applicable for Farcaster casts");
1325
+ this.runtime.logger.debug("[Farcaster] Mark as read is not applicable for Farcaster casts");
1007
1326
  }
1008
- };
1327
+ }
1009
1328
 
1010
1329
  // src/services/CastService.ts
1011
1330
  import {
1012
- logger as logger7,
1331
+ logger as logger6,
1013
1332
  ModelType as ModelType2,
1014
1333
  createUniqueUuid as createUniqueUuid4
1015
1334
  } from "@elizaos/core";
1016
- var FarcasterCastService = class {
1335
+ init_constants();
1336
+
1337
+ class FarcasterCastService {
1338
+ client;
1339
+ runtime;
1340
+ static serviceType = "ICastService";
1017
1341
  constructor(client, runtime) {
1018
1342
  this.client = client;
1019
1343
  this.runtime = runtime;
1020
1344
  }
1021
- static serviceType = "ICastService";
1022
- /**
1023
- * Get recent casts from the timeline
1024
- */
1025
1345
  async getCasts(params) {
1026
- var _a, _b;
1027
1346
  try {
1347
+ const fidStr = this.runtime.getSetting("FARCASTER_FID");
1348
+ const fid = fidStr ? parseInt(fidStr, 10) : NaN;
1349
+ if (!fid || isNaN(fid)) {
1350
+ logger6.error("FARCASTER_FID is not configured");
1351
+ return [];
1352
+ }
1028
1353
  const { timeline } = await this.client.getTimeline({
1029
- fid: ((_a = this.runtime.config) == null ? void 0 : _a.FARCASTER_FID) || ((_b = this.runtime.settings) == null ? void 0 : _b.FARCASTER_FID),
1354
+ fid,
1030
1355
  pageSize: params.limit || 50
1031
1356
  });
1032
1357
  return timeline.map((cast) => this.castToFarcasterCast(cast, params.agentId));
1033
1358
  } catch (error) {
1034
- logger7.error("Failed to get casts", { params, error });
1359
+ logger6.error(`Failed to get casts: ${JSON.stringify({ params, error })}`);
1035
1360
  return [];
1036
1361
  }
1037
1362
  }
1038
- /**
1039
- * Create a new cast
1040
- */
1041
1363
  async createCast(params) {
1042
- var _a;
1043
1364
  try {
1044
1365
  let castText = params.text;
1045
1366
  if (!castText || castText.trim() === "") {
@@ -1050,7 +1371,7 @@ var FarcasterCastService = class {
1050
1371
  }
1051
1372
  const casts = await this.client.sendCast({
1052
1373
  content: { text: castText },
1053
- inReplyTo: params.replyTo ? { hash: params.replyTo.hash, fid: params.replyTo.fid } : void 0
1374
+ inReplyTo: params.replyTo ? { hash: params.replyTo.hash, fid: params.replyTo.fid } : undefined
1054
1375
  });
1055
1376
  if (casts.length === 0) {
1056
1377
  throw new Error("No cast was created");
@@ -1064,9 +1385,8 @@ var FarcasterCastService = class {
1064
1385
  username: cast.profile.username,
1065
1386
  text: cast.text,
1066
1387
  timestamp: cast.timestamp.getTime(),
1067
- inReplyTo: (_a = params.replyTo) == null ? void 0 : _a.hash,
1388
+ inReplyTo: params.replyTo?.hash,
1068
1389
  media: [],
1069
- // TODO: Handle media upload when Farcaster API supports it
1070
1390
  metadata: {
1071
1391
  castHash: cast.hash,
1072
1392
  threadId: cast.threadId,
@@ -1077,73 +1397,60 @@ var FarcasterCastService = class {
1077
1397
  await this.storeCastInMemory(params.roomId, farcasterCast);
1078
1398
  return farcasterCast;
1079
1399
  } catch (error) {
1080
- logger7.error("Failed to create cast", { params, error });
1400
+ logger6.error(`Failed to create cast: ${JSON.stringify({ params, error })}`);
1081
1401
  throw error;
1082
1402
  }
1083
1403
  }
1084
- /**
1085
- * Delete a cast
1086
- */
1087
1404
  async deleteCast(params) {
1088
1405
  try {
1089
- logger7.warn("Cast deletion is not supported by the Farcaster API", { castHash: params.castHash });
1406
+ logger6.warn(`Cast deletion is not supported by the Farcaster API: ${JSON.stringify({ castHash: params.castHash })}`);
1090
1407
  } catch (error) {
1091
- logger7.error("Failed to delete cast", { params, error });
1408
+ logger6.error(`Failed to delete cast: ${JSON.stringify({ params, error })}`);
1092
1409
  throw error;
1093
1410
  }
1094
1411
  }
1095
- /**
1096
- * Like a cast
1097
- */
1098
1412
  async likeCast(params) {
1099
1413
  try {
1100
- logger7.info("Like functionality not yet implemented for cast", { castHash: params.castHash });
1414
+ logger6.info(`Like functionality not yet implemented for cast: ${JSON.stringify({ castHash: params.castHash })}`);
1101
1415
  } catch (error) {
1102
- logger7.error("Failed to like cast", { params, error });
1416
+ logger6.error(`Failed to like cast: ${JSON.stringify({ params, error })}`);
1103
1417
  throw error;
1104
1418
  }
1105
1419
  }
1106
- /**
1107
- * Unlike a cast
1108
- */
1109
1420
  async unlikeCast(params) {
1110
1421
  try {
1111
- logger7.info("Unlike functionality not yet implemented for cast", { castHash: params.castHash });
1422
+ logger6.info(`Unlike functionality not yet implemented for cast: ${JSON.stringify({ castHash: params.castHash })}`);
1112
1423
  } catch (error) {
1113
- logger7.error("Failed to unlike cast", { params, error });
1424
+ logger6.error(`Failed to unlike cast: ${JSON.stringify({ params, error })}`);
1114
1425
  throw error;
1115
1426
  }
1116
1427
  }
1117
- /**
1118
- * Recast a cast
1119
- */
1120
1428
  async recast(params) {
1121
1429
  try {
1122
- logger7.info("Recast functionality not yet implemented for cast", { castHash: params.castHash });
1430
+ logger6.info(`Recast functionality not yet implemented for cast: ${JSON.stringify({ castHash: params.castHash })}`);
1123
1431
  } catch (error) {
1124
- logger7.error("Failed to recast", { params, error });
1432
+ logger6.error(`Failed to recast: ${JSON.stringify({ params, error })}`);
1125
1433
  throw error;
1126
1434
  }
1127
1435
  }
1128
- /**
1129
- * Remove a recast
1130
- */
1131
1436
  async unrecast(params) {
1132
1437
  try {
1133
- logger7.info("Remove recast functionality not yet implemented for cast", { castHash: params.castHash });
1438
+ logger6.info(`Remove recast functionality not yet implemented for cast: ${JSON.stringify({ castHash: params.castHash })}`);
1134
1439
  } catch (error) {
1135
- logger7.error("Failed to remove recast", { params, error });
1440
+ logger6.error(`Failed to remove recast: ${JSON.stringify({ params, error })}`);
1136
1441
  throw error;
1137
1442
  }
1138
1443
  }
1139
- /**
1140
- * Get mentions
1141
- */
1142
1444
  async getMentions(params) {
1143
- var _a, _b;
1144
1445
  try {
1446
+ const fidStr = this.runtime.getSetting("FARCASTER_FID");
1447
+ const fid = fidStr ? parseInt(fidStr, 10) : NaN;
1448
+ if (!fid || isNaN(fid)) {
1449
+ logger6.error("FARCASTER_FID is not configured");
1450
+ return [];
1451
+ }
1145
1452
  const mentions = await this.client.getMentions({
1146
- fid: ((_a = this.runtime.config) == null ? void 0 : _a.FARCASTER_FID) || ((_b = this.runtime.settings) == null ? void 0 : _b.FARCASTER_FID),
1453
+ fid,
1147
1454
  pageSize: params.limit || 20
1148
1455
  });
1149
1456
  return mentions.map((castWithInteractions) => {
@@ -1151,13 +1458,10 @@ var FarcasterCastService = class {
1151
1458
  return this.castToFarcasterCast(cast, params.agentId);
1152
1459
  });
1153
1460
  } catch (error) {
1154
- logger7.error("Failed to get mentions", { params, error });
1461
+ logger6.error(`Failed to get mentions: ${JSON.stringify({ params, error })}`);
1155
1462
  return [];
1156
1463
  }
1157
1464
  }
1158
- /**
1159
- * Generate cast content using AI
1160
- */
1161
1465
  async generateCastContent() {
1162
1466
  const prompt = `Generate an interesting and engaging Farcaster cast. It should be conversational, authentic, and under 320 characters. Topics can include technology, AI, crypto, decentralized social media, or general observations about life.`;
1163
1467
  try {
@@ -1167,13 +1471,10 @@ var FarcasterCastService = class {
1167
1471
  });
1168
1472
  return response;
1169
1473
  } catch (error) {
1170
- logger7.error("Failed to generate cast content", { error });
1171
- return "Hello Farcaster! \u{1F44B}";
1474
+ logger6.error(`Failed to generate cast content: ${JSON.stringify({ error })}`);
1475
+ return "Hello Farcaster! \uD83D\uDC4B";
1172
1476
  }
1173
1477
  }
1174
- /**
1175
- * Truncate cast to fit character limit
1176
- */
1177
1478
  async truncateCast(text) {
1178
1479
  const prompt = `Shorten this text to under 320 characters while keeping the main message intact: "${text}"`;
1179
1480
  try {
@@ -1187,22 +1488,18 @@ var FarcasterCastService = class {
1187
1488
  }
1188
1489
  return truncated;
1189
1490
  } catch (error) {
1190
- logger7.error("Failed to truncate cast", { error });
1491
+ logger6.error(`Failed to truncate cast: ${JSON.stringify({ error })}`);
1191
1492
  return text.substring(0, 317) + "...";
1192
1493
  }
1193
1494
  }
1194
- /**
1195
- * Store cast in agent memory
1196
- */
1197
1495
  async storeCastInMemory(roomId, cast) {
1198
- var _a;
1199
1496
  try {
1200
1497
  const memory = {
1201
1498
  id: createUniqueUuid4(this.runtime, cast.id),
1202
1499
  agentId: this.runtime.agentId,
1203
1500
  content: {
1204
1501
  text: cast.text,
1205
- castHash: (_a = cast.metadata) == null ? void 0 : _a.castHash,
1502
+ castHash: cast.metadata?.castHash,
1206
1503
  castId: cast.id,
1207
1504
  author: cast.username,
1208
1505
  timestamp: cast.timestamp
@@ -1216,15 +1513,12 @@ var FarcasterCastService = class {
1216
1513
  } else if (this.runtime.memory && typeof this.runtime.memory.create === "function") {
1217
1514
  await this.runtime.memory.create(memory);
1218
1515
  } else {
1219
- logger7.warn("Memory storage method not available in runtime");
1516
+ logger6.warn("Memory storage method not available in runtime");
1220
1517
  }
1221
1518
  } catch (error) {
1222
- logger7.error("Failed to store cast in memory", { error });
1519
+ logger6.error(`Failed to store cast in memory: ${JSON.stringify({ error })}`);
1223
1520
  }
1224
1521
  }
1225
- /**
1226
- * Convert internal Cast type to FarcasterCast
1227
- */
1228
1522
  castToFarcasterCast(cast, agentId) {
1229
1523
  return {
1230
1524
  id: castUuid({ hash: cast.hash, agentId }),
@@ -1235,7 +1529,6 @@ var FarcasterCastService = class {
1235
1529
  text: cast.text,
1236
1530
  timestamp: cast.timestamp.getTime(),
1237
1531
  media: [],
1238
- // Farcaster casts can have embedded media but not in our Cast type
1239
1532
  metadata: {
1240
1533
  castHash: cast.hash,
1241
1534
  threadId: cast.threadId,
@@ -1245,39 +1538,35 @@ var FarcasterCastService = class {
1245
1538
  }
1246
1539
  };
1247
1540
  }
1248
- };
1541
+ }
1249
1542
 
1250
1543
  // src/service.ts
1251
- var FarcasterService = class _FarcasterService extends Service {
1544
+ class FarcasterService extends Service {
1252
1545
  static instance;
1253
- managers = /* @__PURE__ */ new Map();
1254
- messageServices = /* @__PURE__ */ new Map();
1255
- castServices = /* @__PURE__ */ new Map();
1256
- // Properly implement serviceType for discoverability
1546
+ managers = new Map;
1547
+ messageServices = new Map;
1548
+ castServices = new Map;
1257
1549
  static serviceType = FARCASTER_SERVICE_NAME;
1258
- // Add service description
1259
1550
  description = "Farcaster integration service for sending and receiving casts";
1260
1551
  capabilityDescription = "The agent is able to send and receive messages on farcaster";
1261
1552
  static getInstance() {
1262
- if (!_FarcasterService.instance) {
1263
- _FarcasterService.instance = new _FarcasterService();
1553
+ if (!FarcasterService.instance) {
1554
+ FarcasterService.instance = new FarcasterService;
1264
1555
  }
1265
- return _FarcasterService.instance;
1556
+ return FarcasterService.instance;
1266
1557
  }
1267
- // Required by ElizaOS Service base class
1268
1558
  async initialize(runtime) {
1269
- await _FarcasterService.start(runtime);
1559
+ await FarcasterService.start(runtime);
1270
1560
  }
1271
- // Called to start a single Farcaster service
1272
1561
  static async start(runtime) {
1273
- const service = _FarcasterService.getInstance();
1562
+ const service = FarcasterService.getInstance();
1274
1563
  let manager = service.managers.get(runtime.agentId);
1275
1564
  if (manager) {
1276
- logger8.warn("Farcaster service already started", runtime.agentId);
1565
+ logger7.warn({ agentId: runtime.agentId }, "Farcaster service already started");
1277
1566
  return service;
1278
1567
  }
1279
1568
  if (!hasFarcasterEnabled(runtime)) {
1280
- logger8.debug("Farcaster service not enabled", runtime.agentId);
1569
+ logger7.debug({ agentId: runtime.agentId }, "Farcaster service not enabled");
1281
1570
  return service;
1282
1571
  }
1283
1572
  const farcasterConfig = validateFarcasterConfig(runtime);
@@ -1288,59 +1577,48 @@ var FarcasterService = class _FarcasterService extends Service {
1288
1577
  service.messageServices.set(runtime.agentId, messageService);
1289
1578
  service.castServices.set(runtime.agentId, castService);
1290
1579
  await manager.start();
1291
- logger8.success("Farcaster client started", runtime.agentId);
1580
+ logger7.success({ agentId: runtime.agentId }, "Farcaster client started");
1292
1581
  return service;
1293
1582
  }
1294
- // Called to stop a single Farcaster service
1295
1583
  static async stop(runtime) {
1296
- const service = _FarcasterService.getInstance();
1584
+ const service = FarcasterService.getInstance();
1297
1585
  let manager = service.managers.get(runtime.agentId);
1298
1586
  if (manager) {
1299
1587
  await manager.stop();
1300
1588
  service.managers.delete(runtime.agentId);
1301
1589
  service.messageServices.delete(runtime.agentId);
1302
1590
  service.castServices.delete(runtime.agentId);
1303
- logger8.info("Farcaster client stopped", runtime.agentId);
1591
+ logger7.info({ agentId: runtime.agentId }, "Farcaster client stopped");
1304
1592
  } else {
1305
- logger8.debug("Farcaster service not running", runtime.agentId);
1593
+ logger7.debug({ agentId: runtime.agentId }, "Farcaster service not running");
1306
1594
  }
1307
1595
  }
1308
- // Called to stop all Farcaster services
1309
1596
  async stop() {
1310
- logger8.debug("Stopping ALL Farcaster services");
1597
+ logger7.debug("Stopping ALL Farcaster services");
1311
1598
  for (const manager of Array.from(this.managers.values())) {
1312
1599
  const agentId = manager.runtime.agentId;
1313
1600
  try {
1314
- await _FarcasterService.stop(manager.runtime);
1601
+ await FarcasterService.stop(manager.runtime);
1315
1602
  } catch (error) {
1316
- logger8.error("Error stopping Farcaster service", agentId, error);
1603
+ logger7.error({ agentId, error }, "Error stopping Farcaster service");
1317
1604
  }
1318
1605
  }
1319
1606
  }
1320
- // Get the MessageService for a specific agent
1321
1607
  getMessageService(agentId) {
1322
1608
  return this.messageServices.get(agentId);
1323
1609
  }
1324
- /**
1325
- * Get the PostService for a specific agent (for compatibility)
1326
- * @deprecated Use getCastService() instead. Will be removed in a future major release.
1327
- */
1328
1610
  getPostService(agentId) {
1329
1611
  return this.castServices.get(agentId);
1330
1612
  }
1331
- // Get the CastService for a specific agent
1332
1613
  getCastService(agentId) {
1333
1614
  return this.castServices.get(agentId);
1334
1615
  }
1335
- // Add health check method
1336
1616
  async healthCheck() {
1337
1617
  const managerStatuses = {};
1338
1618
  let overallHealthy = true;
1339
1619
  for (const [agentId, manager] of Array.from(this.managers.entries())) {
1340
1620
  try {
1341
- const profile = await manager.client.getProfile(
1342
- parseInt(manager.runtime.getSetting("FARCASTER_FID"))
1343
- );
1621
+ const profile = await manager.client.getProfile(parseInt(manager.runtime.getSetting("FARCASTER_FID")));
1344
1622
  managerStatuses[agentId] = {
1345
1623
  status: "healthy",
1346
1624
  fid: profile.fid,
@@ -1362,16 +1640,16 @@ var FarcasterService = class _FarcasterService extends Service {
1362
1640
  }
1363
1641
  };
1364
1642
  }
1365
- // Get all active managers (for monitoring)
1366
1643
  getActiveManagers() {
1367
1644
  return new Map(this.managers);
1368
1645
  }
1369
- };
1646
+ }
1370
1647
 
1371
1648
  // src/__tests__/suite.ts
1649
+ init_constants();
1372
1650
  import {
1373
1651
  ModelType as ModelType3,
1374
- createUniqueUuid as createUniqueUuid6,
1652
+ createUniqueUuid as createUniqueUuid7,
1375
1653
  logger as logger10
1376
1654
  } from "@elizaos/core";
1377
1655
 
@@ -1389,27 +1667,27 @@ var TEST_IMAGE = {
1389
1667
  };
1390
1668
 
1391
1669
  // src/__tests__/e2e/scenarios.ts
1392
- import { logger as logger9, createUniqueUuid as createUniqueUuid5 } from "@elizaos/core";
1670
+ init_constants();
1671
+ import { logger as logger9, createUniqueUuid as createUniqueUuid6 } from "@elizaos/core";
1393
1672
  var farcasterE2EScenarios = [
1394
1673
  {
1395
1674
  name: "Farcaster Plugin - Agent Introduction",
1396
1675
  async fn(runtime) {
1397
- var _a;
1398
1676
  const service = runtime.getService(FARCASTER_SERVICE_NAME);
1399
1677
  if (!service) {
1400
1678
  throw new Error("Farcaster service not initialized");
1401
1679
  }
1402
- const postService = service.getPostService(runtime.agentId);
1403
- if (!postService) {
1404
- throw new Error("PostService not available");
1680
+ const castService = service.getCastService(runtime.agentId);
1681
+ if (!castService) {
1682
+ throw new Error("CastService not available");
1405
1683
  }
1406
- const introText = `Hello Farcaster! I'm ${runtime.character.name}, an AI agent powered by ElizaOS. Looking forward to connecting with you all! \u{1F916}`;
1407
- const cast = await postService.createPost({
1684
+ const introText = `Hello Farcaster! I'm ${runtime.character.name}, an AI agent powered by ElizaOS. Looking forward to connecting with you all! \uD83E\uDD16`;
1685
+ const cast = await castService.createCast({
1408
1686
  agentId: runtime.agentId,
1409
- roomId: createUniqueUuid5(runtime, "farcaster-timeline"),
1687
+ roomId: createUniqueUuid6(runtime, "farcaster-timeline"),
1410
1688
  text: introText
1411
1689
  });
1412
- if (!cast || !cast.id || !cast.text || !((_a = cast.metadata) == null ? void 0 : _a.castHash)) {
1690
+ if (!cast || !cast.id || !cast.text || !cast.metadata?.castHash) {
1413
1691
  throw new Error("Failed to create introduction cast");
1414
1692
  }
1415
1693
  logger9.info(`Posted introduction cast: ${cast.metadata.castHash}`);
@@ -1432,11 +1710,11 @@ var farcasterE2EScenarios = [
1432
1710
  if (!service) {
1433
1711
  throw new Error("Farcaster service not initialized");
1434
1712
  }
1435
- const postService = service.getPostService(runtime.agentId);
1436
- if (!postService) {
1437
- throw new Error("PostService not available");
1713
+ const castService = service.getCastService(runtime.agentId);
1714
+ if (!castService) {
1715
+ throw new Error("CastService not available");
1438
1716
  }
1439
- const casts = await postService.getPosts({
1717
+ const casts = await castService.getCasts({
1440
1718
  agentId: runtime.agentId,
1441
1719
  limit: 10
1442
1720
  });
@@ -1451,7 +1729,7 @@ var farcasterE2EScenarios = [
1451
1729
  }
1452
1730
  logger9.info(`Latest cast by @${firstCast.username}: ${firstCast.text.substring(0, 50)}...`);
1453
1731
  }
1454
- const mentions = await postService.getMentions(runtime.agentId, { limit: 5 });
1732
+ const mentions = await castService.getMentions({ agentId: runtime.agentId, limit: 5 });
1455
1733
  if (!Array.isArray(mentions)) {
1456
1734
  throw new Error("getMentions did not return an array");
1457
1735
  }
@@ -1461,7 +1739,6 @@ var farcasterE2EScenarios = [
1461
1739
  {
1462
1740
  name: "Farcaster Plugin - Message Send and Retrieve",
1463
1741
  async fn(runtime) {
1464
- var _a;
1465
1742
  const service = runtime.getService(FARCASTER_SERVICE_NAME);
1466
1743
  if (!service) {
1467
1744
  throw new Error("Farcaster service not initialized");
@@ -1470,14 +1747,14 @@ var farcasterE2EScenarios = [
1470
1747
  if (!messageService) {
1471
1748
  throw new Error("MessageService not available");
1472
1749
  }
1473
- const roomId = createUniqueUuid5(runtime, "test-conversation");
1750
+ const roomId = createUniqueUuid6(runtime, "test-conversation");
1474
1751
  const message = await messageService.sendMessage({
1475
1752
  agentId: runtime.agentId,
1476
1753
  roomId,
1477
- text: "Testing message send and retrieve with ElizaOS Farcaster plugin! \u{1F9EA}",
1754
+ text: "Testing message send and retrieve with ElizaOS Farcaster plugin! \uD83E\uDDEA",
1478
1755
  type: "CAST" /* CAST */
1479
1756
  });
1480
- if (!message || !message.id || !((_a = message.metadata) == null ? void 0 : _a.castHash)) {
1757
+ if (!message || !message.id || !message.metadata?.castHash) {
1481
1758
  throw new Error("Failed to send message or missing metadata");
1482
1759
  }
1483
1760
  logger9.info(`Sent cast with hash: ${message.metadata.castHash}`);
@@ -1492,35 +1769,34 @@ var farcasterE2EScenarios = [
1492
1769
  {
1493
1770
  name: "Farcaster Plugin - Reply Threading",
1494
1771
  async fn(runtime) {
1495
- var _a, _b;
1496
1772
  const service = runtime.getService(FARCASTER_SERVICE_NAME);
1497
1773
  if (!service) {
1498
1774
  throw new Error("Farcaster service not initialized");
1499
1775
  }
1500
1776
  const messageService = service.getMessageService(runtime.agentId);
1501
- const postService = service.getPostService(runtime.agentId);
1502
- if (!messageService || !postService) {
1777
+ const castService = service.getCastService(runtime.agentId);
1778
+ if (!messageService || !castService) {
1503
1779
  throw new Error("Services not available");
1504
1780
  }
1505
- const originalCast = await postService.createPost({
1781
+ const originalCast = await castService.createCast({
1506
1782
  agentId: runtime.agentId,
1507
- roomId: createUniqueUuid5(runtime, "reply-test"),
1508
- text: "This is a test cast for reply threading \u{1F9F5}"
1783
+ roomId: createUniqueUuid6(runtime, "reply-test"),
1784
+ text: "This is a test cast for reply threading \uD83E\uDDF5"
1509
1785
  });
1510
- if (!originalCast || !((_a = originalCast.metadata) == null ? void 0 : _a.castHash)) {
1786
+ if (!originalCast || !originalCast.metadata?.castHash) {
1511
1787
  throw new Error("Failed to create original cast");
1512
1788
  }
1513
1789
  const reply = await messageService.sendMessage({
1514
1790
  agentId: runtime.agentId,
1515
1791
  roomId: originalCast.roomId,
1516
- text: "This is a test reply maintaining thread context! \u{1F4AC}",
1792
+ text: "This is a test reply maintaining thread context! \uD83D\uDCAC",
1517
1793
  type: "REPLY",
1518
1794
  replyToId: originalCast.metadata.castHash,
1519
1795
  metadata: {
1520
1796
  parentHash: originalCast.metadata.castHash
1521
1797
  }
1522
1798
  });
1523
- if (!reply || !reply.inReplyTo || !((_b = reply.metadata) == null ? void 0 : _b.castHash)) {
1799
+ if (!reply || !reply.inReplyTo || !reply.metadata?.castHash) {
1524
1800
  throw new Error("Failed to create reply or missing thread context");
1525
1801
  }
1526
1802
  logger9.info(`Created reply ${reply.metadata.castHash} to ${originalCast.metadata.castHash}`);
@@ -1529,11 +1805,11 @@ var farcasterE2EScenarios = [
1529
1805
  {
1530
1806
  name: "Farcaster Plugin - Action Execution",
1531
1807
  async fn(runtime) {
1532
- const { sendCastAction: sendCastAction2 } = await import("./sendCast-OW6DBKQB.js");
1808
+ const { sendCastAction: sendCastAction2 } = await Promise.resolve().then(() => (init_sendCast(), exports_sendCast));
1533
1809
  const mockMessage = {
1534
- id: createUniqueUuid5(runtime, "test-message"),
1810
+ id: createUniqueUuid6(runtime, "test-message"),
1535
1811
  agentId: runtime.agentId,
1536
- roomId: createUniqueUuid5(runtime, "test-room"),
1812
+ roomId: createUniqueUuid6(runtime, "test-room"),
1537
1813
  entityId: runtime.agentId,
1538
1814
  content: {
1539
1815
  text: "Can you post about the ElizaOS framework on Farcaster?"
@@ -1544,34 +1820,30 @@ var farcasterE2EScenarios = [
1544
1820
  if (!shouldExecute) {
1545
1821
  throw new Error("SEND_CAST action validation failed");
1546
1822
  }
1547
- const result = await sendCastAction2.handler(runtime, mockMessage);
1548
- if (!result) {
1549
- throw new Error("SEND_CAST action execution failed");
1550
- }
1823
+ await sendCastAction2.handler(runtime, mockMessage);
1551
1824
  logger9.info("Successfully validated and executed SEND_CAST action");
1552
1825
  }
1553
1826
  },
1554
1827
  {
1555
1828
  name: "Farcaster Plugin - Provider Context",
1556
1829
  async fn(runtime) {
1557
- var _a, _b;
1558
- const { farcasterProfileProvider: farcasterProfileProvider2 } = await import("./profileProvider-TNRU42OO.js");
1559
- const { farcasterTimelineProvider: farcasterTimelineProvider2 } = await import("./timelineProvider-GPRPFEVJ.js");
1830
+ const { farcasterProfileProvider: farcasterProfileProvider2 } = await Promise.resolve().then(() => (init_profileProvider(), exports_profileProvider));
1831
+ const { farcasterTimelineProvider: farcasterTimelineProvider2 } = await Promise.resolve().then(() => (init_timelineProvider(), exports_timelineProvider));
1560
1832
  const mockMessage = {
1561
- id: createUniqueUuid5(runtime, "test-message"),
1833
+ id: createUniqueUuid6(runtime, "test-message"),
1562
1834
  agentId: runtime.agentId,
1563
- roomId: createUniqueUuid5(runtime, "test-room"),
1835
+ roomId: createUniqueUuid6(runtime, "test-room"),
1564
1836
  entityId: runtime.agentId,
1565
1837
  content: { text: "test" },
1566
1838
  createdAt: Date.now()
1567
1839
  };
1568
1840
  const profileContext = await farcasterProfileProvider2.get(runtime, mockMessage, { values: [], data: {}, text: "" });
1569
- if (!profileContext || !profileContext.text || ((_a = profileContext.data) == null ? void 0 : _a.available) === void 0) {
1841
+ if (!profileContext || !profileContext.text || profileContext.data?.available === undefined) {
1570
1842
  throw new Error("Profile provider returned invalid context");
1571
1843
  }
1572
1844
  logger9.info(`Profile provider: ${profileContext.text}`);
1573
1845
  const timelineContext = await farcasterTimelineProvider2.get(runtime, mockMessage, { values: [], data: {}, text: "" });
1574
- if (!timelineContext || !timelineContext.text || ((_b = timelineContext.data) == null ? void 0 : _b.available) === void 0) {
1846
+ if (!timelineContext || !timelineContext.text || timelineContext.data?.available === undefined) {
1575
1847
  throw new Error("Timeline provider returned invalid context");
1576
1848
  }
1577
1849
  logger9.info(`Timeline provider: ${timelineContext.text}`);
@@ -1589,18 +1861,16 @@ var farcasterE2EScenarios = [
1589
1861
  throw new Error("MessageService not available");
1590
1862
  }
1591
1863
  const promises = [];
1592
- for (let i = 0; i < 3; i++) {
1593
- promises.push(
1594
- messageService.sendMessage({
1595
- agentId: runtime.agentId,
1596
- roomId: createUniqueUuid5(runtime, "rate-limit-test"),
1597
- text: `Rate limit test message ${i + 1}`,
1598
- type: "CAST" /* CAST */
1599
- }).catch((error) => {
1600
- logger9.warn(`Expected rate limit error: ${error.message}`);
1601
- return null;
1602
- })
1603
- );
1864
+ for (let i = 0;i < 3; i++) {
1865
+ promises.push(messageService.sendMessage({
1866
+ agentId: runtime.agentId,
1867
+ roomId: createUniqueUuid6(runtime, "rate-limit-test"),
1868
+ text: `Rate limit test message ${i + 1}`,
1869
+ type: "CAST" /* CAST */
1870
+ }).catch((error) => {
1871
+ logger9.warn(`Expected rate limit error: ${error.message}`);
1872
+ return null;
1873
+ }));
1604
1874
  }
1605
1875
  const results = await Promise.all(promises);
1606
1876
  const successfulSends = results.filter((r) => r !== null);
@@ -1618,13 +1888,13 @@ var farcasterE2EScenarios = [
1618
1888
  throw new Error("Farcaster service not initialized");
1619
1889
  }
1620
1890
  const health = await service.healthCheck();
1621
- if (!health || health.healthy === void 0 || !health.details) {
1891
+ if (!health || health.healthy === undefined || !health.details) {
1622
1892
  throw new Error("Health check returned invalid data");
1623
1893
  }
1624
1894
  logger9.info(`Service health: ${health.healthy ? "Healthy" : "Unhealthy"}`);
1625
1895
  logger9.info(`Active managers: ${health.details.activeManagers}`);
1626
1896
  if (!health.healthy) {
1627
- logger9.warn("Service reported unhealthy status:", health.details);
1897
+ logger9.warn({ details: health.details }, "Service reported unhealthy status");
1628
1898
  }
1629
1899
  }
1630
1900
  },
@@ -1635,15 +1905,15 @@ var farcasterE2EScenarios = [
1635
1905
  if (!service) {
1636
1906
  throw new Error("FarcasterService not found");
1637
1907
  }
1638
- const postService = service.getPostService(runtime.agentId);
1639
- if (!postService) {
1640
- throw new Error("PostService not available");
1908
+ const castService = service.getCastService(runtime.agentId);
1909
+ if (!castService) {
1910
+ throw new Error("CastService not available");
1641
1911
  }
1642
- const uniqueMessage = `This is a real E2E test cast from ElizaOS! ID: ${createUniqueUuid5(runtime, "e2e-cast")}`;
1912
+ const uniqueMessage = `This is a real E2E test cast from ElizaOS! ID: ${createUniqueUuid6(runtime, "e2e-cast")}`;
1643
1913
  logger9.info(`Attempting to post cast: "${uniqueMessage}"`);
1644
- const cast = await postService.createPost({
1914
+ const cast = await castService.createCast({
1645
1915
  agentId: runtime.agentId,
1646
- roomId: createUniqueUuid5(runtime, "farcaster-e2e-test"),
1916
+ roomId: createUniqueUuid6(runtime, "farcaster-e2e-test"),
1647
1917
  text: uniqueMessage
1648
1918
  });
1649
1919
  if (!cast || !cast.id) {
@@ -1655,30 +1925,26 @@ var farcasterE2EScenarios = [
1655
1925
  ];
1656
1926
 
1657
1927
  // src/__tests__/suite.ts
1658
- var FarcasterTestSuite = class {
1928
+ class FarcasterTestSuite {
1659
1929
  name = "Farcaster Plugin Tests";
1660
1930
  description = "Test suite for Farcaster plugin functionality";
1661
1931
  manager = null;
1662
1932
  tests;
1663
- /**
1664
- * Constructor for TestSuite class.
1665
- * Initializes an array of test functions to be executed.
1666
- */
1667
1933
  constructor() {
1668
1934
  const hasRealCredentials = !!(process.env.FARCASTER_FID && process.env.FARCASTER_SIGNER_UUID && process.env.FARCASTER_NEYNAR_API_KEY);
1669
1935
  logger10.info("=== Farcaster Test Suite Configuration ===");
1670
- logger10.info(`FID: ${process.env.FARCASTER_FID ? "\u2713 Found" : "\u2717 Missing"}`);
1671
- logger10.info(`Signer UUID: ${process.env.FARCASTER_SIGNER_UUID ? "\u2713 Found" : "\u2717 Missing"}`);
1672
- logger10.info(`API Key: ${process.env.FARCASTER_NEYNAR_API_KEY ? "\u2713 Found" : "\u2717 Missing"}`);
1936
+ logger10.info(`FID: ${process.env.FARCASTER_FID ? " Found" : " Missing"}`);
1937
+ logger10.info(`Signer UUID: ${process.env.FARCASTER_SIGNER_UUID ? " Found" : " Missing"}`);
1938
+ logger10.info(`API Key: ${process.env.FARCASTER_NEYNAR_API_KEY ? " Found" : " Missing"}`);
1673
1939
  logger10.info(`Dry Run: ${process.env.FARCASTER_DRY_RUN || "not set (defaults to false)"}`);
1674
1940
  logger10.info("=========================================");
1675
1941
  if (hasRealCredentials) {
1676
- logger10.success("\u2705 Running with real Farcaster credentials");
1942
+ logger10.success(" Running with real Farcaster credentials");
1677
1943
  this.tests = farcasterE2EScenarios;
1678
1944
  } else {
1679
- logger10.warn("\u26A0\uFE0F Farcaster credentials not found in environment variables");
1680
- logger10.warn("\u26A0\uFE0F Tests will run in mock mode");
1681
- logger10.warn("\u26A0\uFE0F To run real tests, set FARCASTER_FID, FARCASTER_SIGNER_UUID, and FARCASTER_NEYNAR_API_KEY");
1945
+ logger10.warn("⚠️ Farcaster credentials not found in environment variables");
1946
+ logger10.warn("⚠️ Tests will run in mock mode");
1947
+ logger10.warn("⚠️ To run real tests, set FARCASTER_FID, FARCASTER_SIGNER_UUID, and FARCASTER_NEYNAR_API_KEY");
1682
1948
  this.tests = [
1683
1949
  {
1684
1950
  name: "Mock: Check Farcaster Configuration",
@@ -1691,9 +1957,6 @@ var FarcasterTestSuite = class {
1691
1957
  ];
1692
1958
  }
1693
1959
  }
1694
- /**
1695
- * Test that checks if Farcaster is properly configured
1696
- */
1697
1960
  async testMockConfiguration(runtime) {
1698
1961
  logger10.info("Running mock configuration test");
1699
1962
  const fid = runtime.getSetting("FARCASTER_FID");
@@ -1711,9 +1974,6 @@ var FarcasterTestSuite = class {
1711
1974
  logger10.info("- FARCASTER_NEYNAR_API_KEY: Neynar API key");
1712
1975
  }
1713
1976
  }
1714
- /**
1715
- * Test service initialization without real credentials
1716
- */
1717
1977
  async testMockServiceInit(runtime) {
1718
1978
  logger10.info("Running mock service initialization test");
1719
1979
  try {
@@ -1724,24 +1984,18 @@ var FarcasterTestSuite = class {
1724
1984
  }
1725
1985
  logger10.info("Farcaster service is registered but may not be fully initialized");
1726
1986
  if (typeof service.getMessageService === "function") {
1727
- logger10.info("\u2713 getMessageService method exists");
1987
+ logger10.info(" getMessageService method exists");
1728
1988
  }
1729
1989
  if (typeof service.getPostService === "function") {
1730
- logger10.info("\u2713 getPostService method exists");
1990
+ logger10.info(" getPostService method exists");
1731
1991
  }
1732
1992
  if (typeof service.healthCheck === "function") {
1733
- logger10.info("\u2713 healthCheck method exists");
1993
+ logger10.info(" healthCheck method exists");
1734
1994
  }
1735
1995
  } catch (error) {
1736
1996
  logger10.info("Service initialization check completed");
1737
1997
  }
1738
1998
  }
1739
- /**
1740
- * Asynchronously initializes the Farcaster client for the provided agent runtime.
1741
- *
1742
- * @param {IAgentRuntime} runtime - The agent runtime to use for initializing the Farcaster client.
1743
- * @throws {Error} If the Farcaster client manager is not found or if the Farcaster client fails to initialize.
1744
- */
1745
1999
  async testInitializingClient(runtime) {
1746
2000
  try {
1747
2001
  const service = runtime.getService(FARCASTER_SERVICE_NAME);
@@ -1758,12 +2012,6 @@ var FarcasterTestSuite = class {
1758
2012
  throw new Error(`Error in initializing Farcaster client: ${error}`);
1759
2013
  }
1760
2014
  }
1761
- /**
1762
- * Asynchronously fetches the profile of a user from Farcaster using the given runtime.
1763
- *
1764
- * @param {IAgentRuntime} runtime The runtime to use for fetching the profile.
1765
- * @returns {Promise<void>} A Promise that resolves when the profile is successfully fetched, or rejects with an error.
1766
- */
1767
2015
  async testFetchProfile(runtime) {
1768
2016
  try {
1769
2017
  if (!this.manager) {
@@ -1777,18 +2025,11 @@ var FarcasterTestSuite = class {
1777
2025
  if (!profile || !profile.fid) {
1778
2026
  throw new Error("Profile fetch failed.");
1779
2027
  }
1780
- logger10.log("Successfully fetched Farcaster profile:", profile);
2028
+ runtime.logger.info({ profile }, "Successfully fetched Farcaster profile:");
1781
2029
  } catch (error) {
1782
2030
  throw new Error(`Error fetching Farcaster profile: ${error}`);
1783
2031
  }
1784
2032
  }
1785
- /**
1786
- * Asynchronously fetches the timeline from the Farcaster client.
1787
- *
1788
- * @param {IAgentRuntime} runtime - The agent runtime object.
1789
- * @throws {Error} If there are no casts in the timeline.
1790
- * @throws {Error} If an error occurs while fetching the timeline.
1791
- */
1792
2033
  async testFetchTimeline(runtime) {
1793
2034
  try {
1794
2035
  if (!this.manager) {
@@ -1808,13 +2049,6 @@ var FarcasterTestSuite = class {
1808
2049
  throw new Error(`Error fetching timeline: ${error}`);
1809
2050
  }
1810
2051
  }
1811
- /**
1812
- * Asynchronously posts a test cast using the Farcaster API.
1813
- *
1814
- * @param {IAgentRuntime} runtime - The agent runtime object.
1815
- * @returns {Promise<void>} A Promise that resolves when the cast is successfully posted.
1816
- * @throws {Error} If there is an error posting the cast.
1817
- */
1818
2052
  async testPostCast(runtime) {
1819
2053
  try {
1820
2054
  if (!this.manager) {
@@ -1832,14 +2066,6 @@ var FarcasterTestSuite = class {
1832
2066
  throw new Error(`Error posting a cast: ${error}`);
1833
2067
  }
1834
2068
  }
1835
- /**
1836
- * Asynchronously posts an image cast on Farcaster using the provided runtime and cast content.
1837
- * Note: This might need updating based on how images are actually handled in sendCast
1838
- *
1839
- * @param {IAgentRuntime} runtime - The runtime environment for the action.
1840
- * @returns {Promise<void>} A Promise that resolves when the cast is successfully posted.
1841
- * @throws {Error} If there is an error posting the cast.
1842
- */
1843
2069
  async testPostImageCast(runtime) {
1844
2070
  try {
1845
2071
  if (!this.manager) {
@@ -1860,13 +2086,6 @@ var FarcasterTestSuite = class {
1860
2086
  throw new Error(`Error posting a cast with image: ${error}`);
1861
2087
  }
1862
2088
  }
1863
- /**
1864
- * Asynchronously handles a fake cast response using the given runtime.
1865
- *
1866
- * @param {IAgentRuntime} runtime - The runtime object for the agent
1867
- * @returns {Promise<void>} - A promise that resolves when the cast response is handled
1868
- * @throws {Error} - If there is an error handling the cast response
1869
- */
1870
2089
  async testHandleCastResponse(runtime) {
1871
2090
  try {
1872
2091
  if (!this.manager) {
@@ -1881,17 +2100,17 @@ var FarcasterTestSuite = class {
1881
2100
  username: "randomUser",
1882
2101
  name: "Random User"
1883
2102
  },
1884
- timestamp: /* @__PURE__ */ new Date()
2103
+ timestamp: new Date
1885
2104
  };
1886
- const memoryId = createUniqueUuid6(runtime, testCast.hash);
2105
+ const memoryId = createUniqueUuid7(runtime, testCast.hash);
1887
2106
  const memory = {
1888
2107
  id: memoryId,
1889
2108
  agentId: runtime.agentId,
1890
2109
  content: {
1891
2110
  text: testCast.text
1892
2111
  },
1893
- entityId: createUniqueUuid6(runtime, String(testCast.authorFid)),
1894
- roomId: createUniqueUuid6(runtime, "test-room"),
2112
+ entityId: createUniqueUuid7(runtime, String(testCast.authorFid)),
2113
+ roomId: createUniqueUuid7(runtime, "test-room"),
1895
2114
  createdAt: testCast.timestamp.getTime()
1896
2115
  };
1897
2116
  runtime.emitEvent("farcaster.mention_received", {
@@ -1905,13 +2124,6 @@ var FarcasterTestSuite = class {
1905
2124
  throw new Error(`Error handling cast response: ${error}`);
1906
2125
  }
1907
2126
  }
1908
- /**
1909
- * Generates random content for a cast based on the given context.
1910
- *
1911
- * @param {IAgentRuntime} runtime - The runtime environment.
1912
- * @param {string} context - Optional context for the content generation.
1913
- * @returns {Promise<string>} A promise that resolves to the generated cast content.
1914
- */
1915
2127
  async generateRandomCastContent(runtime, context = "general") {
1916
2128
  const prompt = `Generate a short, interesting cast about ${context} (max 280 chars).`;
1917
2129
  const result = await runtime.useModel(ModelType3.TEXT_SMALL, {
@@ -1919,12 +2131,6 @@ var FarcasterTestSuite = class {
1919
2131
  });
1920
2132
  return result.substring(0, 280);
1921
2133
  }
1922
- /**
1923
- * Tests the MessageService functionality
1924
- *
1925
- * @param {IAgentRuntime} runtime - The runtime environment.
1926
- * @returns {Promise<void>} A promise that resolves when the test is complete.
1927
- */
1928
2134
  async testMessageService(runtime) {
1929
2135
  try {
1930
2136
  const service = runtime.getService(FARCASTER_SERVICE_NAME);
@@ -1943,7 +2149,7 @@ var FarcasterTestSuite = class {
1943
2149
  const testText = await this.generateRandomCastContent(runtime, "message_service_test");
1944
2150
  const message = await messageService.sendMessage({
1945
2151
  agentId: runtime.agentId,
1946
- roomId: createUniqueUuid6(runtime, "test-room"),
2152
+ roomId: createUniqueUuid7(runtime, "test-room"),
1947
2153
  text: testText,
1948
2154
  type: "CAST" /* CAST */
1949
2155
  });
@@ -1955,12 +2161,6 @@ var FarcasterTestSuite = class {
1955
2161
  throw new Error(`Error testing MessageService: ${error}`);
1956
2162
  }
1957
2163
  }
1958
- /**
1959
- * Tests the PostService functionality
1960
- *
1961
- * @param {IAgentRuntime} runtime - The runtime environment.
1962
- * @returns {Promise<void>} A promise that resolves when the test is complete.
1963
- */
1964
2164
  async testPostService(runtime) {
1965
2165
  try {
1966
2166
  const service = runtime.getService(FARCASTER_SERVICE_NAME);
@@ -1979,7 +2179,7 @@ var FarcasterTestSuite = class {
1979
2179
  const testText = await this.generateRandomCastContent(runtime, "cast_service_test");
1980
2180
  const cast = await castService.createCast({
1981
2181
  agentId: runtime.agentId,
1982
- roomId: createUniqueUuid6(runtime, "test-room"),
2182
+ roomId: createUniqueUuid7(runtime, "test-room"),
1983
2183
  text: testText
1984
2184
  });
1985
2185
  if (!cast || !cast.id) {
@@ -1990,14 +2190,7 @@ var FarcasterTestSuite = class {
1990
2190
  throw new Error(`Error testing PostService: ${error}`);
1991
2191
  }
1992
2192
  }
1993
- /**
1994
- * Tests real account posting functionality
1995
- *
1996
- * @param {IAgentRuntime} runtime - The runtime environment.
1997
- * @returns {Promise<void>} A promise that resolves when the test is complete.
1998
- */
1999
2193
  async testRealAccountPosting(runtime) {
2000
- var _a;
2001
2194
  try {
2002
2195
  const service = runtime.getService(FARCASTER_SERVICE_NAME);
2003
2196
  if (!service) {
@@ -2008,35 +2201,28 @@ var FarcasterTestSuite = class {
2008
2201
  throw new Error("PostService not initialized");
2009
2202
  }
2010
2203
  const testPosts = [
2011
- "Testing ElizaOS Farcaster integration! \u{1F680} #ElizaOS",
2012
- "AI agents are the future of social media engagement \u{1F916}",
2013
- "Building amazing things with the ElizaOS framework \u{1F4BB}"
2204
+ "Testing ElizaOS Farcaster integration! \uD83D\uDE80 #ElizaOS",
2205
+ "AI agents are the future of social media engagement \uD83E\uDD16",
2206
+ "Building amazing things with the ElizaOS framework \uD83D\uDCBB"
2014
2207
  ];
2015
2208
  for (const text of testPosts) {
2016
2209
  const post = await postService.createPost({
2017
2210
  agentId: runtime.agentId,
2018
- roomId: createUniqueUuid6(runtime, "real-test"),
2211
+ roomId: createUniqueUuid7(runtime, "real-test"),
2019
2212
  text
2020
2213
  });
2021
- if (!post || !post.id || !((_a = post.metadata) == null ? void 0 : _a.castHash)) {
2214
+ if (!post || !post.id || !post.metadata?.castHash) {
2022
2215
  throw new Error("Failed to create real post");
2023
2216
  }
2024
2217
  logger10.success(`Posted real cast: ${post.metadata.castHash}`);
2025
- await new Promise((resolve) => setTimeout(resolve, 1e3));
2218
+ await new Promise((resolve) => setTimeout(resolve, 1000));
2026
2219
  }
2027
2220
  logger10.success("Real account posting test completed successfully");
2028
2221
  } catch (error) {
2029
2222
  throw new Error(`Error testing real account posting: ${error}`);
2030
2223
  }
2031
2224
  }
2032
- /**
2033
- * Tests real account interactions (mentions, replies, etc)
2034
- *
2035
- * @param {IAgentRuntime} runtime - The runtime environment.
2036
- * @returns {Promise<void>} A promise that resolves when the test is complete.
2037
- */
2038
2225
  async testRealAccountInteractions(runtime) {
2039
- var _a, _b;
2040
2226
  try {
2041
2227
  const service = runtime.getService(FARCASTER_SERVICE_NAME);
2042
2228
  if (!service) {
@@ -2056,18 +2242,18 @@ var FarcasterTestSuite = class {
2056
2242
  logger10.log(`Found ${timeline.length} timeline posts`);
2057
2243
  if (timeline.length > 0) {
2058
2244
  const targetPost = timeline[0];
2059
- if ((_a = targetPost.metadata) == null ? void 0 : _a.castHash) {
2245
+ if (targetPost.metadata?.castHash) {
2060
2246
  const reply = await messageService.sendMessage({
2061
2247
  agentId: runtime.agentId,
2062
2248
  roomId: targetPost.roomId,
2063
- text: "Great post! Testing real interactions with ElizaOS \u{1F389}",
2249
+ text: "Great post! Testing real interactions with ElizaOS \uD83C\uDF89",
2064
2250
  type: "REPLY" /* REPLY */,
2065
2251
  replyToId: targetPost.metadata.castHash,
2066
2252
  metadata: {
2067
2253
  parentHash: targetPost.metadata.castHash
2068
2254
  }
2069
2255
  });
2070
- if (reply && ((_b = reply.metadata) == null ? void 0 : _b.castHash)) {
2256
+ if (reply && reply.metadata?.castHash) {
2071
2257
  logger10.success(`Replied to cast with: ${reply.metadata.castHash}`);
2072
2258
  }
2073
2259
  }
@@ -2077,14 +2263,7 @@ var FarcasterTestSuite = class {
2077
2263
  throw new Error(`Error testing real account interactions: ${error}`);
2078
2264
  }
2079
2265
  }
2080
- /**
2081
- * Tests message metadata tracking functionality
2082
- *
2083
- * @param {IAgentRuntime} runtime - The runtime environment.
2084
- * @returns {Promise<void>} A promise that resolves when the test is complete.
2085
- */
2086
2266
  async testMessageMetadataTracking(runtime) {
2087
- var _a, _b;
2088
2267
  try {
2089
2268
  const service = runtime.getService(FARCASTER_SERVICE_NAME);
2090
2269
  if (!service) {
@@ -2096,11 +2275,11 @@ var FarcasterTestSuite = class {
2096
2275
  }
2097
2276
  const testMessage = await messageService.sendMessage({
2098
2277
  agentId: runtime.agentId,
2099
- roomId: createUniqueUuid6(runtime, "metadata-test"),
2278
+ roomId: createUniqueUuid7(runtime, "metadata-test"),
2100
2279
  text: "Testing metadata tracking with ElizaOS",
2101
2280
  type: "CAST" /* CAST */
2102
2281
  });
2103
- if (!testMessage || !((_a = testMessage.metadata) == null ? void 0 : _a.castHash)) {
2282
+ if (!testMessage || !testMessage.metadata?.castHash) {
2104
2283
  throw new Error("Failed to send test message");
2105
2284
  }
2106
2285
  const castHash = testMessage.metadata.castHash;
@@ -2109,7 +2288,7 @@ var FarcasterTestSuite = class {
2109
2288
  if (!retrievedMessage) {
2110
2289
  throw new Error("Failed to retrieve message by hash");
2111
2290
  }
2112
- if (((_b = retrievedMessage.metadata) == null ? void 0 : _b.castHash) !== castHash) {
2291
+ if (retrievedMessage.metadata?.castHash !== castHash) {
2113
2292
  throw new Error("Metadata mismatch in retrieved message");
2114
2293
  }
2115
2294
  logger10.success("Message metadata tracking test completed successfully");
@@ -2117,12 +2296,13 @@ var FarcasterTestSuite = class {
2117
2296
  throw new Error(`Error testing message metadata tracking: ${error}`);
2118
2297
  }
2119
2298
  }
2120
- };
2299
+ }
2300
+
2301
+ // src/actions/index.ts
2302
+ init_sendCast();
2121
2303
 
2122
2304
  // src/actions/replyCast.ts
2123
- import {
2124
- logger as logger11
2125
- } from "@elizaos/core";
2305
+ init_constants();
2126
2306
  var replyCastAction = {
2127
2307
  name: "REPLY_TO_CAST",
2128
2308
  description: "Replies to a cast on Farcaster",
@@ -2155,31 +2335,29 @@ var replyCastAction = {
2155
2335
  ]
2156
2336
  ],
2157
2337
  validate: async (runtime, message) => {
2158
- var _a;
2159
- const text = ((_a = message.content.text) == null ? void 0 : _a.toLowerCase()) || "";
2338
+ const text = message.content.text?.toLowerCase() || "";
2160
2339
  const keywords = ["reply", "respond", "answer", "comment"];
2161
2340
  const hasKeyword = keywords.some((keyword) => text.includes(keyword));
2162
2341
  const hasParentCast = !!(message.content.metadata && message.content.metadata.parentCastHash);
2163
2342
  const service = runtime.getService(FARCASTER_SERVICE_NAME);
2164
- const isServiceAvailable = !!(service == null ? void 0 : service.getMessageService(runtime.agentId));
2343
+ const isServiceAvailable = !!service?.getMessageService(runtime.agentId);
2165
2344
  return hasKeyword && (hasParentCast || isServiceAvailable);
2166
2345
  },
2167
2346
  handler: async (runtime, message, state) => {
2168
- var _a;
2169
2347
  try {
2170
2348
  const service = runtime.getService(FARCASTER_SERVICE_NAME);
2171
- const messageService = service == null ? void 0 : service.getMessageService(runtime.agentId);
2349
+ const messageService = service?.getMessageService(runtime.agentId);
2172
2350
  if (!messageService) {
2173
- logger11.error("[REPLY_TO_CAST] MessageService not available");
2174
- return false;
2351
+ runtime.logger.error("[REPLY_TO_CAST] MessageService not available");
2352
+ return;
2175
2353
  }
2176
- const parentCastHash = ((_a = message.content.metadata) == null ? void 0 : _a.parentCastHash) || (state == null ? void 0 : state.parentCastHash);
2354
+ const parentCastHash = message.content.metadata?.parentCastHash || state?.parentCastHash;
2177
2355
  if (!parentCastHash) {
2178
- logger11.error("[REPLY_TO_CAST] No parent cast to reply to");
2179
- return false;
2356
+ runtime.logger.error("[REPLY_TO_CAST] No parent cast to reply to");
2357
+ return;
2180
2358
  }
2181
2359
  let replyContent = "";
2182
- if (state == null ? void 0 : state.replyContent) {
2360
+ if (state?.replyContent) {
2183
2361
  replyContent = state.replyContent;
2184
2362
  } else {
2185
2363
  const prompt = `Based on this request: "${message.content.text}", generate a helpful and engaging reply for a Farcaster cast (max 320 characters).`;
@@ -2199,20 +2377,151 @@ var replyCastAction = {
2199
2377
  parentHash: parentCastHash
2200
2378
  }
2201
2379
  });
2202
- logger11.info(`[REPLY_TO_CAST] Successfully replied to cast: ${reply.id}`);
2203
- return true;
2380
+ runtime.logger.info(`[REPLY_TO_CAST] Successfully replied to cast: ${reply.id}`);
2204
2381
  } catch (error) {
2205
- logger11.error("[REPLY_TO_CAST] Error replying to cast:", error);
2206
- return false;
2382
+ runtime.logger.error("[REPLY_TO_CAST] Error replying to cast:", typeof error === "string" ? error : error.message);
2383
+ throw error;
2207
2384
  }
2208
2385
  }
2209
2386
  };
2210
2387
 
2211
2388
  // src/actions/index.ts
2389
+ init_sendCast();
2212
2390
  var farcasterActions = [sendCastAction, replyCastAction];
2213
2391
 
2214
2392
  // src/providers/index.ts
2215
- var farcasterProviders = [farcasterProfileProvider, farcasterTimelineProvider];
2393
+ init_profileProvider();
2394
+ init_timelineProvider();
2395
+
2396
+ // src/providers/threadProvider.ts
2397
+ init_constants();
2398
+ var formatTimestamp = (timestamp) => {
2399
+ return new Date(timestamp).toLocaleString("en-US", {
2400
+ hour: "2-digit",
2401
+ minute: "2-digit",
2402
+ month: "short",
2403
+ day: "numeric"
2404
+ });
2405
+ };
2406
+ var farcasterThreadProvider = {
2407
+ name: "farcasterThread",
2408
+ description: "Provides thread context for Farcaster casts so the agent can reference the full conversation.",
2409
+ get: async (runtime, message, _state) => {
2410
+ const source = message.content?.source;
2411
+ if (source !== FARCASTER_SOURCE) {
2412
+ return {
2413
+ text: "",
2414
+ data: {
2415
+ available: false,
2416
+ reason: `Not a Farcaster message (source=${source ?? "unknown"})`
2417
+ }
2418
+ };
2419
+ }
2420
+ const service = runtime.getService(FARCASTER_SERVICE_NAME);
2421
+ const messageService = service?.getMessageService(runtime.agentId);
2422
+ if (!messageService) {
2423
+ return {
2424
+ text: "Farcaster message service not available.",
2425
+ data: { available: false, error: "service_unavailable" }
2426
+ };
2427
+ }
2428
+ const content = message.content;
2429
+ const messageMetadata = message.metadata ?? {};
2430
+ const castHash = content.hash || content.castHash || content?.metadata?.castHash || messageMetadata.castHash || content?.metadata?.parentHash || messageMetadata.parentHash;
2431
+ if (!castHash || typeof castHash !== "string") {
2432
+ return {
2433
+ text: "Unable to resolve Farcaster cast hash for this message.",
2434
+ data: { available: false, error: "missing_cast_hash" }
2435
+ };
2436
+ }
2437
+ const threadMessages = await messageService.getThread({
2438
+ agentId: runtime.agentId,
2439
+ castHash
2440
+ });
2441
+ if (!threadMessages || threadMessages.length === 0) {
2442
+ runtime.logger.debug({ castHash }, "[FarcasterThreadProvider] No thread messages retrieved for cast.");
2443
+ return {
2444
+ text: "No Farcaster thread context available.",
2445
+ data: { available: false, castHash, count: 0 }
2446
+ };
2447
+ }
2448
+ const formattedThread = threadMessages.map((msg, index) => {
2449
+ const time = formatTimestamp(msg.timestamp);
2450
+ const username = msg.username || msg.userId || "unknown";
2451
+ const marker = index === threadMessages.length - 1 ? "→" : "•";
2452
+ const text = msg.text && msg.text.trim().length > 0 ? msg.text : "<no text>";
2453
+ return `${marker} [${time}] @${username}: ${text}`;
2454
+ }).join(`
2455
+ `);
2456
+ return {
2457
+ text: `# Farcaster Thread Context
2458
+ ${formattedThread}`,
2459
+ data: {
2460
+ available: true,
2461
+ castHash,
2462
+ count: threadMessages.length
2463
+ },
2464
+ values: {
2465
+ farcasterThread: formattedThread,
2466
+ farcasterCastHash: castHash,
2467
+ farcasterCurrentCastText: threadMessages[threadMessages.length - 1]?.text ?? "",
2468
+ farcasterParentCastText: threadMessages.length > 1 ? threadMessages[threadMessages.length - 2]?.text ?? "" : ""
2469
+ }
2470
+ };
2471
+ }
2472
+ };
2473
+
2474
+ // src/providers/index.ts
2475
+ init_profileProvider();
2476
+ init_timelineProvider();
2477
+ var farcasterProviders = [
2478
+ farcasterProfileProvider,
2479
+ farcasterTimelineProvider,
2480
+ farcasterThreadProvider
2481
+ ];
2482
+
2483
+ // src/routes/webhook.ts
2484
+ var farcasterWebhookRoutes = [
2485
+ {
2486
+ type: "POST",
2487
+ name: "Farcaster Webhook Handler",
2488
+ path: "/webhook",
2489
+ handler: async (req, res, runtime) => {
2490
+ try {
2491
+ const webhookData = req.body;
2492
+ const eventType = webhookData.type;
2493
+ const farcasterService = runtime?.getService?.("farcaster");
2494
+ if (farcasterService) {
2495
+ const agentManager = farcasterService.managers?.get?.(runtime.agentId);
2496
+ if (agentManager && agentManager.interactions) {
2497
+ if (agentManager.interactions.mode === "webhook") {
2498
+ console.log("Processing webhook through FarcasterInteractionManager...");
2499
+ await agentManager.interactions.processWebhookData(webhookData);
2500
+ } else {
2501
+ console.warn(`Agent is in ${agentManager.interactions.mode} mode, not webhook mode`);
2502
+ }
2503
+ } else {
2504
+ console.warn(`FarcasterAgentManager not found for agent ${runtime.agentId}`);
2505
+ }
2506
+ } else {
2507
+ console.warn("FarcasterService not found - webhook data logged only");
2508
+ }
2509
+ res.status(200).json({
2510
+ success: true,
2511
+ message: "Webhook processed successfully",
2512
+ event_type: eventType,
2513
+ timestamp: new Date().toISOString()
2514
+ });
2515
+ } catch (error) {
2516
+ console.error("Webhook processing error:", error);
2517
+ res.status(500).json({
2518
+ success: false,
2519
+ error: "Internal server error"
2520
+ });
2521
+ }
2522
+ }
2523
+ }
2524
+ ];
2216
2525
 
2217
2526
  // src/index.ts
2218
2527
  var farcasterPlugin = {
@@ -2221,10 +2530,12 @@ var farcasterPlugin = {
2221
2530
  services: [FarcasterService],
2222
2531
  actions: farcasterActions,
2223
2532
  providers: farcasterProviders,
2224
- tests: [new FarcasterTestSuite()]
2533
+ routes: farcasterWebhookRoutes,
2534
+ tests: [new FarcasterTestSuite]
2225
2535
  };
2226
- var index_default = farcasterPlugin;
2536
+ var src_default = farcasterPlugin;
2227
2537
  export {
2228
- index_default as default
2538
+ src_default as default
2229
2539
  };
2230
- //# sourceMappingURL=index.js.map
2540
+
2541
+ //# debugId=4C5340413D630C6A64756E2164756E21