a tool to help your Letta AI agents navigate bluesky
1import {
2 agentContext,
3 claimTaskThread,
4 releaseTaskThread,
5} from "../utils/agentContext.ts";
6import {
7 msFrom,
8 msRandomOffset,
9 msUntilNextWakeWindow,
10} from "../utils/time.ts";
11
12export const logStats = () => {
13 if (!claimTaskThread()) {
14 const newDelay = msFrom.minutes(2);
15 console.log(
16 `Stat log attempt failed, ${agentContext.agentBskyName} is busy. Next attempt in ${
17 (newDelay / 1000) / 60
18 } minutes…`,
19 );
20 // session is busy, logging stats in 5~10 minutes.
21 setTimeout(logStats, newDelay);
22 return;
23 }
24
25 const delay = msUntilNextWakeWindow(
26 msFrom.minutes(30),
27 msFrom.hours(1),
28 );
29
30 if (delay !== 0) {
31 setTimeout(logStats, delay);
32 console.log(
33 `🔹 ${agentContext.agentBskyName} is currently asleep. scheduling next stat log for ${
34 (delay / 1000 / 60 / 60).toFixed(2)
35 } hours from now…`,
36 );
37 releaseTaskThread();
38 return;
39 }
40
41 // Check if there are any notifications
42 const totalNotifications = agentContext.mentionCount +
43 agentContext.likeCount +
44 agentContext.repostCount +
45 agentContext.quoteCount +
46 agentContext.replyCount +
47 agentContext.followCount;
48
49 const nextCheckDelay = msFrom.minutes(5);
50 const nextCheckMinutes = ((nextCheckDelay / 1000) / 60).toFixed(1);
51
52 if (totalNotifications <= 0) {
53 console.log(
54 `no engagement stats yet... next check in ${nextCheckMinutes} minutes…`,
55 );
56 } else {
57 const counts = [];
58
59 if (agentContext.mentionCount > 0) {
60 counts.push(
61 `${agentContext.mentionCount} ${
62 agentContext.mentionCount === 1 ? "mention" : "mentions"
63 }`,
64 );
65 }
66 if (agentContext.likeCount > 0) {
67 counts.push(
68 `${agentContext.likeCount} ${
69 agentContext.likeCount === 1 ? "like" : "likes"
70 }`,
71 );
72 }
73 if (agentContext.repostCount > 0) {
74 counts.push(
75 `${agentContext.repostCount} ${
76 agentContext.repostCount === 1 ? "repost" : "reposts"
77 }`,
78 );
79 }
80 if (agentContext.quoteCount > 0) {
81 counts.push(
82 `${agentContext.quoteCount} ${
83 agentContext.quoteCount === 1 ? "quote" : "quotes"
84 }`,
85 );
86 }
87 if (agentContext.replyCount > 0) {
88 counts.push(
89 `${agentContext.replyCount} ${
90 agentContext.replyCount === 1 ? "reply" : "replies"
91 }`,
92 );
93 }
94 if (agentContext.followCount > 0) {
95 counts.push(
96 `${agentContext.followCount} new ${
97 agentContext.followCount === 1 ? "follower" : "followers"
98 }`,
99 );
100 }
101
102 const message = counts.join(", ");
103 const suffix = agentContext.reflectionEnabled
104 ? " since last reflection"
105 : "";
106 console.log(
107 `
108stats: ${message}${suffix}. next check in ${nextCheckMinutes} minutes…`,
109 );
110 }
111 setTimeout(logStats, nextCheckDelay);
112 releaseTaskThread();
113};