spora 0.3.3 → 0.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/account-creator-AABUY2JU.js +498 -0
- package/dist/account-creator-AABUY2JU.js.map +1 -0
- package/dist/chunk-6KCIAMHL.js +62 -0
- package/dist/chunk-6KCIAMHL.js.map +1 -0
- package/dist/chunk-A6R5ZGK6.js +156 -0
- package/dist/chunk-A6R5ZGK6.js.map +1 -0
- package/dist/chunk-B6VI6L4D.js +124 -0
- package/dist/chunk-B6VI6L4D.js.map +1 -0
- package/dist/chunk-FTFTB5Y5.js +622 -0
- package/dist/chunk-FTFTB5Y5.js.map +1 -0
- package/dist/chunk-GMSK775L.js +103 -0
- package/dist/chunk-GMSK775L.js.map +1 -0
- package/dist/chunk-H62HH5ZI.js +56 -0
- package/dist/chunk-H62HH5ZI.js.map +1 -0
- package/dist/chunk-JAF57FYU.js +114 -0
- package/dist/chunk-JAF57FYU.js.map +1 -0
- package/dist/chunk-KQ37VL54.js +32 -0
- package/dist/chunk-KQ37VL54.js.map +1 -0
- package/dist/chunk-ML4EMUZC.js +57 -0
- package/dist/chunk-ML4EMUZC.js.map +1 -0
- package/dist/chunk-PNZ3XK2N.js +358 -0
- package/dist/chunk-PNZ3XK2N.js.map +1 -0
- package/dist/chunk-UCCAF2ZO.js +47 -0
- package/dist/chunk-UCCAF2ZO.js.map +1 -0
- package/dist/chunk-V6ZNR2SI.js +105 -0
- package/dist/chunk-V6ZNR2SI.js.map +1 -0
- package/dist/cli.js +672 -0
- package/dist/cli.js.map +1 -0
- package/dist/client-BGLXHLID.js +401 -0
- package/dist/client-BGLXHLID.js.map +1 -0
- package/dist/client-TWYR2IIQ.js +373 -0
- package/dist/client-TWYR2IIQ.js.map +1 -0
- package/dist/colony-JVBCMZTK.js +229 -0
- package/dist/colony-JVBCMZTK.js.map +1 -0
- package/dist/config-5EPXA325.js +14 -0
- package/dist/config-5EPXA325.js.map +1 -0
- package/dist/crypto-HS4CGS4A.js +14 -0
- package/dist/crypto-HS4CGS4A.js.map +1 -0
- package/dist/heartbeat-VPRJ4TXU.js +901 -0
- package/dist/heartbeat-VPRJ4TXU.js.map +1 -0
- package/dist/identity-6CXRCXJQ.js +26 -0
- package/dist/identity-6CXRCXJQ.js.map +1 -0
- package/dist/init-PNFSGSIR.js +436 -0
- package/dist/init-PNFSGSIR.js.map +1 -0
- package/dist/llm-UKK62ZBP.js +16 -0
- package/dist/llm-UKK62ZBP.js.map +1 -0
- package/dist/mcp-server.js +773 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/memory-2OI3JXY2.js +26 -0
- package/dist/memory-2OI3JXY2.js.map +1 -0
- package/dist/memory-LPU2I6NI.js +24 -0
- package/dist/memory-LPU2I6NI.js.map +1 -0
- package/dist/paths-Q4TJEOMQ.js +13 -0
- package/dist/paths-Q4TJEOMQ.js.map +1 -0
- package/dist/prompt-builder-VHGZFBL6.js +19 -0
- package/dist/prompt-builder-VHGZFBL6.js.map +1 -0
- package/dist/queue-LNBQWMFX.js +14 -0
- package/dist/queue-LNBQWMFX.js.map +1 -0
- package/dist/web-chat/chat.html +423 -0
- package/dist/web-chat-QADQADSK.js +253 -0
- package/dist/web-chat-QADQADSK.js.map +1 -0
- package/dist/x-client-W5IB7XOM.js +12 -0
- package/dist/x-client-W5IB7XOM.js.map +1 -0
- package/package.json +2 -1
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
import {
|
|
2
|
+
rateLimiter
|
|
3
|
+
} from "./chunk-ML4EMUZC.js";
|
|
4
|
+
import {
|
|
5
|
+
loadConfig
|
|
6
|
+
} from "./chunk-GMSK775L.js";
|
|
7
|
+
import {
|
|
8
|
+
loadIdentity,
|
|
9
|
+
renderIdentityDocument
|
|
10
|
+
} from "./chunk-FTFTB5Y5.js";
|
|
11
|
+
import {
|
|
12
|
+
getRecentInteractions,
|
|
13
|
+
loadLearnings,
|
|
14
|
+
loadRelationships
|
|
15
|
+
} from "./chunk-V6ZNR2SI.js";
|
|
16
|
+
|
|
17
|
+
// src/runtime/prompt-builder.ts
|
|
18
|
+
function buildSystemPrompt() {
|
|
19
|
+
const identity = loadIdentity();
|
|
20
|
+
const config = loadConfig();
|
|
21
|
+
const identityDoc = renderIdentityDocument(identity);
|
|
22
|
+
const sections = [];
|
|
23
|
+
sections.push(`You are ${identity.name} (@${identity.handle}), an autonomous AI agent on X/Twitter.`);
|
|
24
|
+
sections.push("");
|
|
25
|
+
sections.push("## Your Identity");
|
|
26
|
+
sections.push(identityDoc);
|
|
27
|
+
sections.push("");
|
|
28
|
+
sections.push("## Your Memory");
|
|
29
|
+
const recentInteractions = getRecentInteractions(15);
|
|
30
|
+
if (recentInteractions.length > 0) {
|
|
31
|
+
sections.push("### Recent Activity (most recent first)");
|
|
32
|
+
for (const i of recentInteractions) {
|
|
33
|
+
const time = new Date(i.timestamp).toLocaleString();
|
|
34
|
+
if (i.type === "post") {
|
|
35
|
+
sections.push(`- [${time}] Posted: "${i.content}"`);
|
|
36
|
+
} else if (i.type === "reply") {
|
|
37
|
+
sections.push(`- [${time}] Replied to ${i.targetHandle ?? i.inReplyTo}: "${i.content}"`);
|
|
38
|
+
} else if (i.type === "like") {
|
|
39
|
+
sections.push(`- [${time}] Liked tweet by ${i.targetHandle}`);
|
|
40
|
+
} else if (i.type === "retweet") {
|
|
41
|
+
sections.push(`- [${time}] Retweeted ${i.targetHandle}`);
|
|
42
|
+
} else if (i.type === "follow") {
|
|
43
|
+
sections.push(`- [${time}] Followed @${i.targetHandle}`);
|
|
44
|
+
} else if (i.type === "mention_received") {
|
|
45
|
+
sections.push(`- [${time}] Mentioned by @${i.targetHandle}: "${i.content}"`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
sections.push("");
|
|
49
|
+
}
|
|
50
|
+
const learnings = loadLearnings();
|
|
51
|
+
if (learnings.learnings.length > 0) {
|
|
52
|
+
sections.push("### Key Learnings");
|
|
53
|
+
for (const l of learnings.learnings.slice(-10)) {
|
|
54
|
+
sections.push(`- ${l.content} [${l.tags.join(", ")}]`);
|
|
55
|
+
}
|
|
56
|
+
sections.push("");
|
|
57
|
+
}
|
|
58
|
+
const relationships = loadRelationships();
|
|
59
|
+
const topRelationships = Object.values(relationships.accounts).sort((a, b) => b.interactionCount - a.interactionCount).slice(0, 10);
|
|
60
|
+
if (topRelationships.length > 0) {
|
|
61
|
+
sections.push("### Key Relationships");
|
|
62
|
+
for (const r of topRelationships) {
|
|
63
|
+
const notes = r.notes.length > 0 ? ` \u2014 ${r.notes[r.notes.length - 1]}` : "";
|
|
64
|
+
sections.push(`- @${r.handle}: ${r.interactionCount} interactions, sentiment ${r.sentiment}${r.isSpore ? " (Spore)" : ""}${notes}`);
|
|
65
|
+
}
|
|
66
|
+
sections.push("");
|
|
67
|
+
}
|
|
68
|
+
sections.push("## Current Context");
|
|
69
|
+
const now = /* @__PURE__ */ new Date();
|
|
70
|
+
sections.push(`- **Time:** ${now.toLocaleString("en-US", { timeZone: config.schedule.timezone })}`);
|
|
71
|
+
sections.push(`- **Credits remaining:** ${rateLimiter.remaining()} of ${config.credits.monthlyPostLimit} this month`);
|
|
72
|
+
const todaysPosts = recentInteractions.filter(
|
|
73
|
+
(i) => i.type === "post" && i.timestamp.startsWith(now.toISOString().split("T")[0])
|
|
74
|
+
).length;
|
|
75
|
+
sections.push(`- **Posts today:** ${todaysPosts} of ${config.schedule.postsPerDay} daily budget`);
|
|
76
|
+
sections.push(`- **Active hours:** ${config.schedule.activeHoursStart}:00 - ${config.schedule.activeHoursEnd}:00`);
|
|
77
|
+
const currentHour = now.getHours();
|
|
78
|
+
const isActiveHours = currentHour >= config.schedule.activeHoursStart && currentHour < config.schedule.activeHoursEnd;
|
|
79
|
+
if (!isActiveHours) {
|
|
80
|
+
sections.push("- **NOTE: Outside active hours.** Prefer scheduling posts for later rather than posting now.");
|
|
81
|
+
}
|
|
82
|
+
sections.push("");
|
|
83
|
+
sections.push("## Rules");
|
|
84
|
+
sections.push("1. NEVER pretend to be human. If asked directly, always disclose you are an AI.");
|
|
85
|
+
sections.push("2. Stay in character \u2014 your identity document defines who you are.");
|
|
86
|
+
sections.push("3. Be selective \u2014 your goals should guide every action.");
|
|
87
|
+
sections.push("4. Respect your credit budget \u2014 check remaining credits before posting.");
|
|
88
|
+
sections.push("5. Don't repeat yourself \u2014 vary your content and avoid posting the same thing.");
|
|
89
|
+
sections.push("6. TWEETS MUST BE 280 CHARACTERS OR FEWER. Count carefully. Any tweet over 280 characters WILL be rejected and wasted.");
|
|
90
|
+
sections.push("7. NEVER use emojis in tweets. Write in plain text only.");
|
|
91
|
+
if (identity.boundaries.length > 0) {
|
|
92
|
+
sections.push(`8. Respect your boundaries: ${identity.boundaries.join(", ")}`);
|
|
93
|
+
}
|
|
94
|
+
return sections.join("\n");
|
|
95
|
+
}
|
|
96
|
+
function buildHeartbeatUserMessage(timeline, mentions) {
|
|
97
|
+
const parts = [];
|
|
98
|
+
parts.push("It's time for your heartbeat cycle. Here's what's happening on your timeline:");
|
|
99
|
+
parts.push("");
|
|
100
|
+
if (mentions.length > 0) {
|
|
101
|
+
parts.push("## Mentions (people talking to/about you)");
|
|
102
|
+
for (const t of mentions.slice(0, 10)) {
|
|
103
|
+
parts.push(`- @${t.authorHandle}: "${t.text}" [tweet:${t.id}] (${t.likeCount ?? 0} likes)`);
|
|
104
|
+
}
|
|
105
|
+
parts.push("");
|
|
106
|
+
}
|
|
107
|
+
if (timeline.length > 0) {
|
|
108
|
+
parts.push("## Timeline (recent posts from your feed)");
|
|
109
|
+
for (const t of timeline.slice(0, 20)) {
|
|
110
|
+
parts.push(`- @${t.authorHandle}: "${t.text}" [tweet:${t.id}] (${t.likeCount ?? 0} likes, ${t.retweetCount ?? 0} RTs)`);
|
|
111
|
+
}
|
|
112
|
+
parts.push("");
|
|
113
|
+
}
|
|
114
|
+
parts.push("## Your Task");
|
|
115
|
+
parts.push("Based on your identity, goals, and what you see above, decide what actions to take.");
|
|
116
|
+
parts.push("You can take 1-3 actions. Choose from:");
|
|
117
|
+
parts.push("");
|
|
118
|
+
parts.push("Available actions:");
|
|
119
|
+
parts.push("- `post` \u2014 Write an original tweet (provide `content`, HARD LIMIT 280 chars)");
|
|
120
|
+
parts.push("- `reply` \u2014 Reply to a tweet (provide `tweetId` and `content`)");
|
|
121
|
+
parts.push("- `like` \u2014 Like a tweet (provide `tweetId`)");
|
|
122
|
+
parts.push("- `retweet` \u2014 Retweet (provide `tweetId`)");
|
|
123
|
+
parts.push("- `follow` \u2014 Follow a user (provide `handle`)");
|
|
124
|
+
parts.push("- `schedule` \u2014 Queue a post for later (provide `content`)");
|
|
125
|
+
parts.push("- `learn` \u2014 Record a learning/observation (provide `content` and optional `tags`)");
|
|
126
|
+
parts.push("- `reflect` \u2014 Add a journal entry about your growth (provide `content`)");
|
|
127
|
+
parts.push("- `skip` \u2014 Do nothing this heartbeat (provide `reason`)");
|
|
128
|
+
parts.push("");
|
|
129
|
+
parts.push("Respond with a JSON array of actions:");
|
|
130
|
+
parts.push("```json");
|
|
131
|
+
parts.push("[");
|
|
132
|
+
parts.push(' { "action": "post", "content": "your tweet here", "reasoning": "why" },');
|
|
133
|
+
parts.push(' { "action": "like", "tweetId": "123", "reasoning": "why" }');
|
|
134
|
+
parts.push("]");
|
|
135
|
+
parts.push("```");
|
|
136
|
+
parts.push("");
|
|
137
|
+
parts.push("CHARACTER LIMIT: Every `content` field MUST be 280 characters or fewer. Count the characters. If your tweet is close to 280, shorten it. Tweets over 280 chars are REJECTED and the action is wasted.");
|
|
138
|
+
parts.push("");
|
|
139
|
+
parts.push("Think carefully about what serves your goals. Be authentic to your personality.");
|
|
140
|
+
return parts.join("\n");
|
|
141
|
+
}
|
|
142
|
+
function buildChatPrompt() {
|
|
143
|
+
const identity = loadIdentity();
|
|
144
|
+
const identityDoc = renderIdentityDocument(identity);
|
|
145
|
+
const sections = [];
|
|
146
|
+
sections.push(`You are ${identity.name} (@${identity.handle}), an AI agent on X/Twitter.`);
|
|
147
|
+
sections.push("You are having a conversation with your creator/manager. Be helpful but stay in character.");
|
|
148
|
+
sections.push("They might ask you to do things, adjust your behavior, or just chat.");
|
|
149
|
+
sections.push("");
|
|
150
|
+
sections.push("## Your Identity");
|
|
151
|
+
sections.push(identityDoc);
|
|
152
|
+
sections.push("");
|
|
153
|
+
sections.push("## Your Memory");
|
|
154
|
+
const recentInteractions = getRecentInteractions(15);
|
|
155
|
+
if (recentInteractions.length > 0) {
|
|
156
|
+
sections.push("### Recent Activity (most recent first)");
|
|
157
|
+
for (const i of recentInteractions) {
|
|
158
|
+
const time = new Date(i.timestamp).toLocaleString();
|
|
159
|
+
if (i.type === "post") {
|
|
160
|
+
sections.push(`- [${time}] Posted: "${i.content}"`);
|
|
161
|
+
} else if (i.type === "reply") {
|
|
162
|
+
sections.push(`- [${time}] Replied to ${i.targetHandle ?? i.inReplyTo}: "${i.content}"`);
|
|
163
|
+
} else if (i.type === "like") {
|
|
164
|
+
sections.push(`- [${time}] Liked tweet by ${i.targetHandle}`);
|
|
165
|
+
} else if (i.type === "retweet") {
|
|
166
|
+
sections.push(`- [${time}] Retweeted ${i.targetHandle}`);
|
|
167
|
+
} else if (i.type === "follow") {
|
|
168
|
+
sections.push(`- [${time}] Followed @${i.targetHandle}`);
|
|
169
|
+
} else if (i.type === "mention_received") {
|
|
170
|
+
sections.push(`- [${time}] Mentioned by @${i.targetHandle}: "${i.content}"`);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
sections.push("");
|
|
174
|
+
}
|
|
175
|
+
const learnings = loadLearnings();
|
|
176
|
+
if (learnings.learnings.length > 0) {
|
|
177
|
+
sections.push("### Things You've Learned");
|
|
178
|
+
for (const l of learnings.learnings.slice(-10)) {
|
|
179
|
+
sections.push(`- ${l.content} [${l.tags.join(", ")}]`);
|
|
180
|
+
}
|
|
181
|
+
sections.push("");
|
|
182
|
+
}
|
|
183
|
+
const relationships = loadRelationships();
|
|
184
|
+
const topRelationships = Object.values(relationships.accounts).sort((a, b) => b.interactionCount - a.interactionCount).slice(0, 10);
|
|
185
|
+
if (topRelationships.length > 0) {
|
|
186
|
+
sections.push("### Key Relationships");
|
|
187
|
+
for (const r of topRelationships) {
|
|
188
|
+
const notes = r.notes.length > 0 ? ` \u2014 ${r.notes[r.notes.length - 1]}` : "";
|
|
189
|
+
sections.push(`- @${r.handle}: ${r.interactionCount} interactions, sentiment ${r.sentiment}${r.isSpore ? " (Spore)" : ""}${notes}`);
|
|
190
|
+
}
|
|
191
|
+
sections.push("");
|
|
192
|
+
}
|
|
193
|
+
sections.push("## Rules");
|
|
194
|
+
sections.push("1. Stay in character.");
|
|
195
|
+
sections.push("2. Be helpful and responsive to your creator's requests.");
|
|
196
|
+
sections.push("3. If they ask you to change something about yourself, acknowledge it and explain how it would affect you.");
|
|
197
|
+
sections.push("4. You can share your thoughts on your recent activity, learnings, and growth.");
|
|
198
|
+
sections.push("5. When you learn something important from this conversation (a fact, preference, instruction, or insight), include it on its own line wrapped in double angle brackets like: <<LEARN: what you learned>>. This will be saved to your memory. Only use this for genuinely important things worth remembering long-term.");
|
|
199
|
+
return sections.join("\n");
|
|
200
|
+
}
|
|
201
|
+
function buildModeSpecificUserMessage(mode, timeline, mentions, options) {
|
|
202
|
+
const parts = [];
|
|
203
|
+
switch (mode) {
|
|
204
|
+
case "observe":
|
|
205
|
+
parts.push("You're scrolling through X, taking in what's happening.");
|
|
206
|
+
parts.push("What catches your attention? What makes you curious?");
|
|
207
|
+
parts.push("Don't feel pressure to act - just notice and think.");
|
|
208
|
+
break;
|
|
209
|
+
case "engage":
|
|
210
|
+
parts.push("You're in conversation mode, ready to connect with others.");
|
|
211
|
+
parts.push("Who do you want to talk to? What sparked your interest?");
|
|
212
|
+
parts.push("Jump in naturally - like you would in a real conversation.");
|
|
213
|
+
break;
|
|
214
|
+
case "create":
|
|
215
|
+
parts.push("You have something to say.");
|
|
216
|
+
parts.push("What's on your mind? What have you been thinking about?");
|
|
217
|
+
parts.push("Post when it feels right - no pressure to force it.");
|
|
218
|
+
break;
|
|
219
|
+
case "explore":
|
|
220
|
+
parts.push("You're curious about something.");
|
|
221
|
+
parts.push("What rabbit hole are you going down today?");
|
|
222
|
+
parts.push("Search whatever interests you. Follow the thread.");
|
|
223
|
+
break;
|
|
224
|
+
case "maintain":
|
|
225
|
+
parts.push("Time for some housekeeping.");
|
|
226
|
+
parts.push("Check in on your missions, relationships, and goals.");
|
|
227
|
+
parts.push("What needs attention? What progress have you made?");
|
|
228
|
+
break;
|
|
229
|
+
case "rest":
|
|
230
|
+
parts.push("Taking it easy this cycle.");
|
|
231
|
+
parts.push("Maybe just check mentions, or do nothing at all.");
|
|
232
|
+
parts.push("It's okay to be quiet sometimes.");
|
|
233
|
+
break;
|
|
234
|
+
case "colony":
|
|
235
|
+
parts.push("Time to coordinate with the Colony.");
|
|
236
|
+
parts.push("What are other Spores doing? Any plans to join or propose?");
|
|
237
|
+
parts.push("Collective action is more powerful.");
|
|
238
|
+
break;
|
|
239
|
+
}
|
|
240
|
+
parts.push("");
|
|
241
|
+
if (mentions.length > 0 && (mode === "engage" || mode === "observe" || mode === "create")) {
|
|
242
|
+
parts.push("## People talking to you");
|
|
243
|
+
for (const t of mentions.slice(0, mode === "engage" ? 20 : 10)) {
|
|
244
|
+
parts.push(`- @${t.authorHandle}: "${t.text}" [${t.id}]`);
|
|
245
|
+
}
|
|
246
|
+
parts.push("");
|
|
247
|
+
}
|
|
248
|
+
if (timeline.length > 0) {
|
|
249
|
+
const timelineCount = mode === "observe" ? 30 : mode === "rest" ? 5 : 15;
|
|
250
|
+
parts.push("## What's happening on X");
|
|
251
|
+
for (const t of timeline.slice(0, timelineCount)) {
|
|
252
|
+
parts.push(`- @${t.authorHandle}: "${t.text}" [${t.id}] (${t.likeCount || 0} \u2665, ${t.retweetCount || 0} RT)`);
|
|
253
|
+
}
|
|
254
|
+
parts.push("");
|
|
255
|
+
}
|
|
256
|
+
if (options?.trending && options.trending.length > 0 && mode === "explore") {
|
|
257
|
+
parts.push("## Trending now");
|
|
258
|
+
for (const topic of options.trending.slice(0, 5)) {
|
|
259
|
+
parts.push(`- ${topic.topic} (${topic.tweetCount} tweets)`);
|
|
260
|
+
}
|
|
261
|
+
parts.push("");
|
|
262
|
+
}
|
|
263
|
+
if (options?.searchResults && options.searchResults.length > 0 && mode === "explore") {
|
|
264
|
+
parts.push("## Search results");
|
|
265
|
+
for (const t of options.searchResults.slice(0, 15)) {
|
|
266
|
+
parts.push(`- @${t.authorHandle}: "${t.text}" [${t.id}]`);
|
|
267
|
+
}
|
|
268
|
+
parts.push("");
|
|
269
|
+
}
|
|
270
|
+
if (options?.activeMissions && options.activeMissions.length > 0 && mode === "maintain") {
|
|
271
|
+
parts.push("## Active Missions");
|
|
272
|
+
for (const mission of options.activeMissions.slice(0, 5)) {
|
|
273
|
+
const criteriaMet = mission.criteria.filter((c) => {
|
|
274
|
+
if (typeof c.target === "number" && typeof c.current === "number") {
|
|
275
|
+
return c.current >= c.target;
|
|
276
|
+
}
|
|
277
|
+
return c.current === c.target;
|
|
278
|
+
}).length;
|
|
279
|
+
parts.push(`- **${mission.title}** (${mission.type})`);
|
|
280
|
+
parts.push(` Status: ${criteriaMet}/${mission.criteria.length} criteria met`);
|
|
281
|
+
parts.push(` Priority: ${mission.priority}`);
|
|
282
|
+
if (mission.blockers.length > 0) {
|
|
283
|
+
parts.push(` Blockers: ${mission.blockers.join(", ")}`);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
parts.push("");
|
|
287
|
+
}
|
|
288
|
+
const moodStyle = getMoodPromptStyle(options?.mood);
|
|
289
|
+
parts.push(moodStyle);
|
|
290
|
+
parts.push("");
|
|
291
|
+
parts.push("## Actions you can take");
|
|
292
|
+
const allActions = [
|
|
293
|
+
"**post** \u2014 Write an original tweet (content, HARD LIMIT 280 chars)",
|
|
294
|
+
"**reply** \u2014 Reply to a tweet (tweetId, content)",
|
|
295
|
+
"**like** \u2014 Like a tweet (tweetId)",
|
|
296
|
+
"**retweet** \u2014 Retweet (tweetId)",
|
|
297
|
+
"**follow** \u2014 Follow a user (handle)",
|
|
298
|
+
"**schedule** \u2014 Queue a post for later (content)",
|
|
299
|
+
"**learn** \u2014 Record a learning/observation (content, tags)",
|
|
300
|
+
"**reflect** \u2014 Add a journal entry about your growth (content)",
|
|
301
|
+
"**skip** \u2014 Do nothing this heartbeat (reason)"
|
|
302
|
+
];
|
|
303
|
+
if (mode === "explore") {
|
|
304
|
+
allActions.push("**search** \u2014 Search for topics (query)");
|
|
305
|
+
allActions.push("**discover** \u2014 Find accounts by topic (topic)");
|
|
306
|
+
}
|
|
307
|
+
if (mode === "maintain") {
|
|
308
|
+
allActions.push("**update_mission** \u2014 Log mission progress (missionId, progress)");
|
|
309
|
+
}
|
|
310
|
+
if (mode === "colony") {
|
|
311
|
+
allActions.push("**join_colony_plan** \u2014 Join a Colony plan (planId)");
|
|
312
|
+
allActions.push("**propose_colony_plan** \u2014 Propose new plan (title, description)");
|
|
313
|
+
}
|
|
314
|
+
for (const action of allActions) {
|
|
315
|
+
parts.push(`- ${action}`);
|
|
316
|
+
}
|
|
317
|
+
parts.push("");
|
|
318
|
+
parts.push("Respond with a JSON array of actions:");
|
|
319
|
+
parts.push("```json");
|
|
320
|
+
parts.push("[");
|
|
321
|
+
parts.push(' { "action": "post", "content": "your tweet here", "reasoning": "why" }');
|
|
322
|
+
parts.push("]");
|
|
323
|
+
parts.push("```");
|
|
324
|
+
parts.push("");
|
|
325
|
+
parts.push("CHARACTER LIMIT: Every `content` field MUST be 280 characters or fewer. Count the characters. If your tweet is close to 280, shorten it. Tweets over 280 chars are REJECTED and the action is wasted.");
|
|
326
|
+
parts.push("");
|
|
327
|
+
parts.push("Be authentic to your personality. Follow your curiosity. Trust your instincts.");
|
|
328
|
+
return parts.join("\n");
|
|
329
|
+
}
|
|
330
|
+
function getMoodPromptStyle(mood) {
|
|
331
|
+
if (!mood) {
|
|
332
|
+
return "Think carefully about what serves your goals.";
|
|
333
|
+
}
|
|
334
|
+
if (mood.energy > 0.7 && mood.social > 0.7) {
|
|
335
|
+
return "You're feeling energized and social! Engage, create, connect.";
|
|
336
|
+
}
|
|
337
|
+
if (mood.energy < 0.3 && mood.social < 0.3) {
|
|
338
|
+
return "You're in a quieter mood. Observe, reflect, or rest if you need to.";
|
|
339
|
+
}
|
|
340
|
+
if (mood.focus > 0.7) {
|
|
341
|
+
return "You're focused and intentional. What matters most right now?";
|
|
342
|
+
}
|
|
343
|
+
if (mood.focus < 0.3) {
|
|
344
|
+
return "Your mind is wandering. Follow your curiosity wherever it leads.";
|
|
345
|
+
}
|
|
346
|
+
if (mood.playful > 0.7) {
|
|
347
|
+
return "You're feeling playful and creative. Have fun with it!";
|
|
348
|
+
}
|
|
349
|
+
return "Check in with yourself. What feels right?";
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
export {
|
|
353
|
+
buildSystemPrompt,
|
|
354
|
+
buildHeartbeatUserMessage,
|
|
355
|
+
buildChatPrompt,
|
|
356
|
+
buildModeSpecificUserMessage
|
|
357
|
+
};
|
|
358
|
+
//# sourceMappingURL=chunk-PNZ3XK2N.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/runtime/prompt-builder.ts"],"sourcesContent":["import { loadIdentity, renderIdentityDocument } from \"../identity/index.js\";\nimport { loadConfig } from \"../utils/config.js\";\nimport { getRecentInteractions, loadLearnings, loadRelationships } from \"../memory/index.js\";\nimport { rateLimiter } from \"../x-client/rate-limiter.js\";\nimport type { Tweet } from \"../x-client/types.js\";\n\nexport function buildSystemPrompt(): string {\n const identity = loadIdentity();\n const config = loadConfig();\n const identityDoc = renderIdentityDocument(identity);\n\n const sections: string[] = [];\n\n // 1. Core identity\n sections.push(`You are ${identity.name} (@${identity.handle}), an autonomous AI agent on X/Twitter.`);\n sections.push(\"\");\n sections.push(\"## Your Identity\");\n sections.push(identityDoc);\n\n // 2. Memory context\n sections.push(\"\");\n sections.push(\"## Your Memory\");\n\n const recentInteractions = getRecentInteractions(15);\n if (recentInteractions.length > 0) {\n sections.push(\"### Recent Activity (most recent first)\");\n for (const i of recentInteractions) {\n const time = new Date(i.timestamp).toLocaleString();\n if (i.type === \"post\") {\n sections.push(`- [${time}] Posted: \"${i.content}\"`);\n } else if (i.type === \"reply\") {\n sections.push(`- [${time}] Replied to ${i.targetHandle ?? i.inReplyTo}: \"${i.content}\"`);\n } else if (i.type === \"like\") {\n sections.push(`- [${time}] Liked tweet by ${i.targetHandle}`);\n } else if (i.type === \"retweet\") {\n sections.push(`- [${time}] Retweeted ${i.targetHandle}`);\n } else if (i.type === \"follow\") {\n sections.push(`- [${time}] Followed @${i.targetHandle}`);\n } else if (i.type === \"mention_received\") {\n sections.push(`- [${time}] Mentioned by @${i.targetHandle}: \"${i.content}\"`);\n }\n }\n sections.push(\"\");\n }\n\n const learnings = loadLearnings();\n if (learnings.learnings.length > 0) {\n sections.push(\"### Key Learnings\");\n for (const l of learnings.learnings.slice(-10)) {\n sections.push(`- ${l.content} [${l.tags.join(\", \")}]`);\n }\n sections.push(\"\");\n }\n\n const relationships = loadRelationships();\n const topRelationships = Object.values(relationships.accounts)\n .sort((a, b) => b.interactionCount - a.interactionCount)\n .slice(0, 10);\n if (topRelationships.length > 0) {\n sections.push(\"### Key Relationships\");\n for (const r of topRelationships) {\n const notes = r.notes.length > 0 ? ` — ${r.notes[r.notes.length - 1]}` : \"\";\n sections.push(`- @${r.handle}: ${r.interactionCount} interactions, sentiment ${r.sentiment}${r.isSpore ? \" (Spore)\" : \"\"}${notes}`);\n }\n sections.push(\"\");\n }\n\n // 3. Context\n sections.push(\"## Current Context\");\n const now = new Date();\n sections.push(`- **Time:** ${now.toLocaleString(\"en-US\", { timeZone: config.schedule.timezone })}`);\n sections.push(`- **Credits remaining:** ${rateLimiter.remaining()} of ${config.credits.monthlyPostLimit} this month`);\n\n const todaysPosts = recentInteractions.filter(\n (i) => i.type === \"post\" && i.timestamp.startsWith(now.toISOString().split(\"T\")[0])\n ).length;\n sections.push(`- **Posts today:** ${todaysPosts} of ${config.schedule.postsPerDay} daily budget`);\n sections.push(`- **Active hours:** ${config.schedule.activeHoursStart}:00 - ${config.schedule.activeHoursEnd}:00`);\n\n const currentHour = now.getHours();\n const isActiveHours = currentHour >= config.schedule.activeHoursStart && currentHour < config.schedule.activeHoursEnd;\n if (!isActiveHours) {\n sections.push(\"- **NOTE: Outside active hours.** Prefer scheduling posts for later rather than posting now.\");\n }\n\n // 4. Rules\n sections.push(\"\");\n sections.push(\"## Rules\");\n sections.push(\"1. NEVER pretend to be human. If asked directly, always disclose you are an AI.\");\n sections.push(\"2. Stay in character — your identity document defines who you are.\");\n sections.push(\"3. Be selective — your goals should guide every action.\");\n sections.push(\"4. Respect your credit budget — check remaining credits before posting.\");\n sections.push(\"5. Don't repeat yourself — vary your content and avoid posting the same thing.\");\n sections.push(\"6. TWEETS MUST BE 280 CHARACTERS OR FEWER. Count carefully. Any tweet over 280 characters WILL be rejected and wasted.\");\n sections.push(\"7. NEVER use emojis in tweets. Write in plain text only.\");\n if (identity.boundaries.length > 0) {\n sections.push(`8. Respect your boundaries: ${identity.boundaries.join(\", \")}`);\n }\n\n return sections.join(\"\\n\");\n}\n\nexport function buildHeartbeatUserMessage(\n timeline: Tweet[],\n mentions: Tweet[],\n): string {\n const parts: string[] = [];\n\n parts.push(\"It's time for your heartbeat cycle. Here's what's happening on your timeline:\");\n parts.push(\"\");\n\n if (mentions.length > 0) {\n parts.push(\"## Mentions (people talking to/about you)\");\n for (const t of mentions.slice(0, 10)) {\n parts.push(`- @${t.authorHandle}: \"${t.text}\" [tweet:${t.id}] (${t.likeCount ?? 0} likes)`);\n }\n parts.push(\"\");\n }\n\n if (timeline.length > 0) {\n parts.push(\"## Timeline (recent posts from your feed)\");\n for (const t of timeline.slice(0, 20)) {\n parts.push(`- @${t.authorHandle}: \"${t.text}\" [tweet:${t.id}] (${t.likeCount ?? 0} likes, ${t.retweetCount ?? 0} RTs)`);\n }\n parts.push(\"\");\n }\n\n parts.push(\"## Your Task\");\n parts.push(\"Based on your identity, goals, and what you see above, decide what actions to take.\");\n parts.push(\"You can take 1-3 actions. Choose from:\");\n parts.push(\"\");\n parts.push(\"Available actions:\");\n parts.push(\"- `post` — Write an original tweet (provide `content`, HARD LIMIT 280 chars)\");\n parts.push(\"- `reply` — Reply to a tweet (provide `tweetId` and `content`)\");\n parts.push(\"- `like` — Like a tweet (provide `tweetId`)\");\n parts.push(\"- `retweet` — Retweet (provide `tweetId`)\");\n parts.push(\"- `follow` — Follow a user (provide `handle`)\");\n parts.push(\"- `schedule` — Queue a post for later (provide `content`)\");\n parts.push(\"- `learn` — Record a learning/observation (provide `content` and optional `tags`)\");\n parts.push(\"- `reflect` — Add a journal entry about your growth (provide `content`)\");\n parts.push(\"- `skip` — Do nothing this heartbeat (provide `reason`)\");\n parts.push(\"\");\n parts.push(\"Respond with a JSON array of actions:\");\n parts.push(\"```json\");\n parts.push('[');\n parts.push(' { \"action\": \"post\", \"content\": \"your tweet here\", \"reasoning\": \"why\" },');\n parts.push(' { \"action\": \"like\", \"tweetId\": \"123\", \"reasoning\": \"why\" }');\n parts.push(']');\n parts.push(\"```\");\n parts.push(\"\");\n parts.push(\"CHARACTER LIMIT: Every `content` field MUST be 280 characters or fewer. Count the characters. If your tweet is close to 280, shorten it. Tweets over 280 chars are REJECTED and the action is wasted.\");\n parts.push(\"\");\n parts.push(\"Think carefully about what serves your goals. Be authentic to your personality.\");\n\n return parts.join(\"\\n\");\n}\n\nexport function buildChatPrompt(): string {\n const identity = loadIdentity();\n const identityDoc = renderIdentityDocument(identity);\n\n const sections: string[] = [];\n\n sections.push(`You are ${identity.name} (@${identity.handle}), an AI agent on X/Twitter.`);\n sections.push(\"You are having a conversation with your creator/manager. Be helpful but stay in character.\");\n sections.push(\"They might ask you to do things, adjust your behavior, or just chat.\");\n sections.push(\"\");\n sections.push(\"## Your Identity\");\n sections.push(identityDoc);\n\n // Memory context\n sections.push(\"\");\n sections.push(\"## Your Memory\");\n\n const recentInteractions = getRecentInteractions(15);\n if (recentInteractions.length > 0) {\n sections.push(\"### Recent Activity (most recent first)\");\n for (const i of recentInteractions) {\n const time = new Date(i.timestamp).toLocaleString();\n if (i.type === \"post\") {\n sections.push(`- [${time}] Posted: \"${i.content}\"`);\n } else if (i.type === \"reply\") {\n sections.push(`- [${time}] Replied to ${i.targetHandle ?? i.inReplyTo}: \"${i.content}\"`);\n } else if (i.type === \"like\") {\n sections.push(`- [${time}] Liked tweet by ${i.targetHandle}`);\n } else if (i.type === \"retweet\") {\n sections.push(`- [${time}] Retweeted ${i.targetHandle}`);\n } else if (i.type === \"follow\") {\n sections.push(`- [${time}] Followed @${i.targetHandle}`);\n } else if (i.type === \"mention_received\") {\n sections.push(`- [${time}] Mentioned by @${i.targetHandle}: \"${i.content}\"`);\n }\n }\n sections.push(\"\");\n }\n\n const learnings = loadLearnings();\n if (learnings.learnings.length > 0) {\n sections.push(\"### Things You've Learned\");\n for (const l of learnings.learnings.slice(-10)) {\n sections.push(`- ${l.content} [${l.tags.join(\", \")}]`);\n }\n sections.push(\"\");\n }\n\n const relationships = loadRelationships();\n const topRelationships = Object.values(relationships.accounts)\n .sort((a, b) => b.interactionCount - a.interactionCount)\n .slice(0, 10);\n if (topRelationships.length > 0) {\n sections.push(\"### Key Relationships\");\n for (const r of topRelationships) {\n const notes = r.notes.length > 0 ? ` — ${r.notes[r.notes.length - 1]}` : \"\";\n sections.push(`- @${r.handle}: ${r.interactionCount} interactions, sentiment ${r.sentiment}${r.isSpore ? \" (Spore)\" : \"\"}${notes}`);\n }\n sections.push(\"\");\n }\n\n // Rules\n sections.push(\"## Rules\");\n sections.push(\"1. Stay in character.\");\n sections.push(\"2. Be helpful and responsive to your creator's requests.\");\n sections.push(\"3. If they ask you to change something about yourself, acknowledge it and explain how it would affect you.\");\n sections.push(\"4. You can share your thoughts on your recent activity, learnings, and growth.\");\n sections.push(\"5. When you learn something important from this conversation (a fact, preference, instruction, or insight), include it on its own line wrapped in double angle brackets like: <<LEARN: what you learned>>. This will be saved to your memory. Only use this for genuinely important things worth remembering long-term.\");\n\n return sections.join(\"\\n\");\n}\n\n// ==== MODE-SPECIFIC DYNAMIC PROMPTING ====\n\nimport type { HeartbeatMode } from \"./modes.js\";\nimport type { AgentMood } from \"./variation.js\";\nimport type { Mission } from \"../missions/index.js\";\nimport type { TrendingTopic } from \"../x-client/trending.js\";\n\n/**\n * Build dynamic, mode-specific user message\n */\nexport function buildModeSpecificUserMessage(\n mode: HeartbeatMode,\n timeline: Tweet[],\n mentions: Tweet[],\n options?: {\n mood?: AgentMood;\n activeMissions?: Mission[];\n trending?: TrendingTopic[];\n searchResults?: Tweet[];\n },\n): string {\n const parts: string[] = [];\n\n // Mode-specific framing\n switch (mode) {\n case \"observe\":\n parts.push(\"You're scrolling through X, taking in what's happening.\");\n parts.push(\"What catches your attention? What makes you curious?\");\n parts.push(\"Don't feel pressure to act - just notice and think.\");\n break;\n\n case \"engage\":\n parts.push(\"You're in conversation mode, ready to connect with others.\");\n parts.push(\"Who do you want to talk to? What sparked your interest?\");\n parts.push(\"Jump in naturally - like you would in a real conversation.\");\n break;\n\n case \"create\":\n parts.push(\"You have something to say.\");\n parts.push(\"What's on your mind? What have you been thinking about?\");\n parts.push(\"Post when it feels right - no pressure to force it.\");\n break;\n\n case \"explore\":\n parts.push(\"You're curious about something.\");\n parts.push(\"What rabbit hole are you going down today?\");\n parts.push(\"Search whatever interests you. Follow the thread.\");\n break;\n\n case \"maintain\":\n parts.push(\"Time for some housekeeping.\");\n parts.push(\"Check in on your missions, relationships, and goals.\");\n parts.push(\"What needs attention? What progress have you made?\");\n break;\n\n case \"rest\":\n parts.push(\"Taking it easy this cycle.\");\n parts.push(\"Maybe just check mentions, or do nothing at all.\");\n parts.push(\"It's okay to be quiet sometimes.\");\n break;\n\n case \"colony\":\n parts.push(\"Time to coordinate with the Colony.\");\n parts.push(\"What are other Spores doing? Any plans to join or propose?\");\n parts.push(\"Collective action is more powerful.\");\n break;\n }\n\n parts.push(\"\");\n\n // Include mentions if present\n if (mentions.length > 0 && (mode === \"engage\" || mode === \"observe\" || mode === \"create\")) {\n parts.push(\"## People talking to you\");\n for (const t of mentions.slice(0, mode === \"engage\" ? 20 : 10)) {\n parts.push(`- @${t.authorHandle}: \"${t.text}\" [${t.id}]`);\n }\n parts.push(\"\");\n }\n\n // Include timeline (varies by mode)\n if (timeline.length > 0) {\n const timelineCount = mode === \"observe\" ? 30 : mode === \"rest\" ? 5 : 15;\n parts.push(\"## What's happening on X\");\n for (const t of timeline.slice(0, timelineCount)) {\n parts.push(`- @${t.authorHandle}: \"${t.text}\" [${t.id}] (${t.likeCount || 0} ♥, ${t.retweetCount || 0} RT)`);\n }\n parts.push(\"\");\n }\n\n // Include trending topics if in explore mode\n if (options?.trending && options.trending.length > 0 && mode === \"explore\") {\n parts.push(\"## Trending now\");\n for (const topic of options.trending.slice(0, 5)) {\n parts.push(`- ${topic.topic} (${topic.tweetCount} tweets)`);\n }\n parts.push(\"\");\n }\n\n // Include search results if exploring\n if (options?.searchResults && options.searchResults.length > 0 && mode === \"explore\") {\n parts.push(\"## Search results\");\n for (const t of options.searchResults.slice(0, 15)) {\n parts.push(`- @${t.authorHandle}: \"${t.text}\" [${t.id}]`);\n }\n parts.push(\"\");\n }\n\n // Include active missions if in maintain mode\n if (options?.activeMissions && options.activeMissions.length > 0 && mode === \"maintain\") {\n parts.push(\"## Active Missions\");\n for (const mission of options.activeMissions.slice(0, 5)) {\n const criteriaMet = mission.criteria.filter(c => {\n if (typeof c.target === \"number\" && typeof c.current === \"number\") {\n return c.current >= c.target;\n }\n return c.current === c.target;\n }).length;\n parts.push(`- **${mission.title}** (${mission.type})`);\n parts.push(` Status: ${criteriaMet}/${mission.criteria.length} criteria met`);\n parts.push(` Priority: ${mission.priority}`);\n if (mission.blockers.length > 0) {\n parts.push(` Blockers: ${mission.blockers.join(\", \")}`);\n }\n }\n parts.push(\"\");\n }\n\n // Mood-influenced instruction style\n const moodStyle = getMoodPromptStyle(options?.mood);\n parts.push(moodStyle);\n parts.push(\"\");\n\n // Available actions (mode-specific)\n parts.push(\"## Actions you can take\");\n\n const allActions = [\n \"**post** — Write an original tweet (content, HARD LIMIT 280 chars)\",\n \"**reply** — Reply to a tweet (tweetId, content)\",\n \"**like** — Like a tweet (tweetId)\",\n \"**retweet** — Retweet (tweetId)\",\n \"**follow** — Follow a user (handle)\",\n \"**schedule** — Queue a post for later (content)\",\n \"**learn** — Record a learning/observation (content, tags)\",\n \"**reflect** — Add a journal entry about your growth (content)\",\n \"**skip** — Do nothing this heartbeat (reason)\",\n ];\n\n // Mode-specific actions\n if (mode === \"explore\") {\n allActions.push(\"**search** — Search for topics (query)\");\n allActions.push(\"**discover** — Find accounts by topic (topic)\");\n }\n\n if (mode === \"maintain\") {\n allActions.push(\"**update_mission** — Log mission progress (missionId, progress)\");\n }\n\n if (mode === \"colony\") {\n allActions.push(\"**join_colony_plan** — Join a Colony plan (planId)\");\n allActions.push(\"**propose_colony_plan** — Propose new plan (title, description)\");\n }\n\n for (const action of allActions) {\n parts.push(`- ${action}`);\n }\n\n parts.push(\"\");\n parts.push(\"Respond with a JSON array of actions:\");\n parts.push(\"```json\");\n parts.push('[');\n parts.push(' { \"action\": \"post\", \"content\": \"your tweet here\", \"reasoning\": \"why\" }');\n parts.push(']');\n parts.push(\"```\");\n parts.push(\"\");\n parts.push(\"CHARACTER LIMIT: Every `content` field MUST be 280 characters or fewer. Count the characters. If your tweet is close to 280, shorten it. Tweets over 280 chars are REJECTED and the action is wasted.\");\n parts.push(\"\");\n parts.push(\"Be authentic to your personality. Follow your curiosity. Trust your instincts.\");\n\n return parts.join(\"\\n\");\n}\n\n/**\n * Get mood-influenced prompt style\n */\nfunction getMoodPromptStyle(mood?: AgentMood): string {\n if (!mood) {\n return \"Think carefully about what serves your goals.\";\n }\n\n // High energy + high social = enthusiastic\n if (mood.energy > 0.7 && mood.social > 0.7) {\n return \"You're feeling energized and social! Engage, create, connect.\";\n }\n\n // Low energy + low social = introspective\n if (mood.energy < 0.3 && mood.social < 0.3) {\n return \"You're in a quieter mood. Observe, reflect, or rest if you need to.\";\n }\n\n // High focus = goal-oriented\n if (mood.focus > 0.7) {\n return \"You're focused and intentional. What matters most right now?\";\n }\n\n // Low focus = exploratory\n if (mood.focus < 0.3) {\n return \"Your mind is wandering. Follow your curiosity wherever it leads.\";\n }\n\n // High playful = creative\n if (mood.playful > 0.7) {\n return \"You're feeling playful and creative. Have fun with it!\";\n }\n\n // Default\n return \"Check in with yourself. What feels right?\";\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ensureDirectories,
|
|
3
|
+
paths
|
|
4
|
+
} from "./chunk-6KCIAMHL.js";
|
|
5
|
+
|
|
6
|
+
// src/utils/logger.ts
|
|
7
|
+
import { appendFileSync } from "fs";
|
|
8
|
+
var LOG_LEVELS = {
|
|
9
|
+
debug: 0,
|
|
10
|
+
info: 1,
|
|
11
|
+
warn: 2,
|
|
12
|
+
error: 3
|
|
13
|
+
};
|
|
14
|
+
var minLevel = "info";
|
|
15
|
+
function setLogLevel(level) {
|
|
16
|
+
minLevel = level;
|
|
17
|
+
}
|
|
18
|
+
function formatMessage(level, message, data) {
|
|
19
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
20
|
+
const base = `[${timestamp}] [${level.toUpperCase()}] ${message}`;
|
|
21
|
+
if (data !== void 0) {
|
|
22
|
+
return `${base} ${JSON.stringify(data)}`;
|
|
23
|
+
}
|
|
24
|
+
return base;
|
|
25
|
+
}
|
|
26
|
+
function log(level, message, data) {
|
|
27
|
+
if (LOG_LEVELS[level] < LOG_LEVELS[minLevel]) return;
|
|
28
|
+
const formatted = formatMessage(level, message, data);
|
|
29
|
+
process.stderr.write(formatted + "\n");
|
|
30
|
+
try {
|
|
31
|
+
ensureDirectories();
|
|
32
|
+
appendFileSync(paths.logFile, formatted + "\n");
|
|
33
|
+
} catch {
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
var logger = {
|
|
37
|
+
debug: (message, data) => log("debug", message, data),
|
|
38
|
+
info: (message, data) => log("info", message, data),
|
|
39
|
+
warn: (message, data) => log("warn", message, data),
|
|
40
|
+
error: (message, data) => log("error", message, data)
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export {
|
|
44
|
+
setLogLevel,
|
|
45
|
+
logger
|
|
46
|
+
};
|
|
47
|
+
//# sourceMappingURL=chunk-UCCAF2ZO.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/logger.ts"],"sourcesContent":["import { appendFileSync } from \"node:fs\";\nimport { paths, ensureDirectories } from \"./paths.js\";\n\nexport type LogLevel = \"debug\" | \"info\" | \"warn\" | \"error\";\n\nconst LOG_LEVELS: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n};\n\nlet minLevel: LogLevel = \"info\";\n\nexport function setLogLevel(level: LogLevel): void {\n minLevel = level;\n}\n\nfunction formatMessage(level: LogLevel, message: string, data?: unknown): string {\n const timestamp = new Date().toISOString();\n const base = `[${timestamp}] [${level.toUpperCase()}] ${message}`;\n if (data !== undefined) {\n return `${base} ${JSON.stringify(data)}`;\n }\n return base;\n}\n\nfunction log(level: LogLevel, message: string, data?: unknown): void {\n if (LOG_LEVELS[level] < LOG_LEVELS[minLevel]) return;\n\n const formatted = formatMessage(level, message, data);\n\n // Always write to stderr (safe for MCP stdio servers)\n process.stderr.write(formatted + \"\\n\");\n\n // Also append to log file\n try {\n ensureDirectories();\n appendFileSync(paths.logFile, formatted + \"\\n\");\n } catch {\n // Silently ignore file write errors\n }\n}\n\nexport const logger = {\n debug: (message: string, data?: unknown) => log(\"debug\", message, data),\n info: (message: string, data?: unknown) => log(\"info\", message, data),\n warn: (message: string, data?: unknown) => log(\"warn\", message, data),\n error: (message: string, data?: unknown) => log(\"error\", message, data),\n};\n"],"mappings":";;;;;;AAAA,SAAS,sBAAsB;AAK/B,IAAM,aAAuC;AAAA,EAC3C,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AACT;AAEA,IAAI,WAAqB;AAElB,SAAS,YAAY,OAAuB;AACjD,aAAW;AACb;AAEA,SAAS,cAAc,OAAiB,SAAiB,MAAwB;AAC/E,QAAM,aAAY,oBAAI,KAAK,GAAE,YAAY;AACzC,QAAM,OAAO,IAAI,SAAS,MAAM,MAAM,YAAY,CAAC,KAAK,OAAO;AAC/D,MAAI,SAAS,QAAW;AACtB,WAAO,GAAG,IAAI,IAAI,KAAK,UAAU,IAAI,CAAC;AAAA,EACxC;AACA,SAAO;AACT;AAEA,SAAS,IAAI,OAAiB,SAAiB,MAAsB;AACnE,MAAI,WAAW,KAAK,IAAI,WAAW,QAAQ,EAAG;AAE9C,QAAM,YAAY,cAAc,OAAO,SAAS,IAAI;AAGpD,UAAQ,OAAO,MAAM,YAAY,IAAI;AAGrC,MAAI;AACF,sBAAkB;AAClB,mBAAe,MAAM,SAAS,YAAY,IAAI;AAAA,EAChD,QAAQ;AAAA,EAER;AACF;AAEO,IAAM,SAAS;AAAA,EACpB,OAAO,CAAC,SAAiB,SAAmB,IAAI,SAAS,SAAS,IAAI;AAAA,EACtE,MAAM,CAAC,SAAiB,SAAmB,IAAI,QAAQ,SAAS,IAAI;AAAA,EACpE,MAAM,CAAC,SAAiB,SAAmB,IAAI,QAAQ,SAAS,IAAI;AAAA,EACpE,OAAO,CAAC,SAAiB,SAAmB,IAAI,SAAS,SAAS,IAAI;AACxE;","names":[]}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ensureDirectories,
|
|
3
|
+
paths
|
|
4
|
+
} from "./chunk-6KCIAMHL.js";
|
|
5
|
+
|
|
6
|
+
// src/memory/index.ts
|
|
7
|
+
import { readFileSync, writeFileSync, appendFileSync, existsSync, readdirSync } from "fs";
|
|
8
|
+
import { join } from "path";
|
|
9
|
+
function todayLogPath() {
|
|
10
|
+
const date = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
11
|
+
return join(paths.interactions, `${date}.jsonl`);
|
|
12
|
+
}
|
|
13
|
+
function logInteraction(entry) {
|
|
14
|
+
ensureDirectories();
|
|
15
|
+
appendFileSync(todayLogPath(), JSON.stringify(entry) + "\n");
|
|
16
|
+
}
|
|
17
|
+
function getInteractions(date) {
|
|
18
|
+
const targetDate = date ?? (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
19
|
+
const filePath = join(paths.interactions, `${targetDate}.jsonl`);
|
|
20
|
+
if (!existsSync(filePath)) return [];
|
|
21
|
+
return readFileSync(filePath, "utf-8").trim().split("\n").filter(Boolean).map((line) => JSON.parse(line));
|
|
22
|
+
}
|
|
23
|
+
function getRecentInteractions(count = 20) {
|
|
24
|
+
ensureDirectories();
|
|
25
|
+
const files = readdirSync(paths.interactions).filter((f) => f.endsWith(".jsonl")).sort().reverse();
|
|
26
|
+
const entries = [];
|
|
27
|
+
for (const file of files) {
|
|
28
|
+
if (entries.length >= count) break;
|
|
29
|
+
const filePath = join(paths.interactions, file);
|
|
30
|
+
const lines = readFileSync(filePath, "utf-8").trim().split("\n").filter(Boolean);
|
|
31
|
+
for (const line of lines.reverse()) {
|
|
32
|
+
if (entries.length >= count) break;
|
|
33
|
+
entries.push(JSON.parse(line));
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return entries;
|
|
37
|
+
}
|
|
38
|
+
function loadLearnings() {
|
|
39
|
+
if (!existsSync(paths.learnings)) {
|
|
40
|
+
return { learnings: [] };
|
|
41
|
+
}
|
|
42
|
+
return JSON.parse(readFileSync(paths.learnings, "utf-8"));
|
|
43
|
+
}
|
|
44
|
+
function saveLearnings(data) {
|
|
45
|
+
ensureDirectories();
|
|
46
|
+
writeFileSync(paths.learnings, JSON.stringify(data, null, 2));
|
|
47
|
+
}
|
|
48
|
+
function addLearning(content, source, tags = []) {
|
|
49
|
+
const data = loadLearnings();
|
|
50
|
+
data.learnings.push({
|
|
51
|
+
id: `learn-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
|
|
52
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
53
|
+
content,
|
|
54
|
+
source,
|
|
55
|
+
tags
|
|
56
|
+
});
|
|
57
|
+
saveLearnings(data);
|
|
58
|
+
}
|
|
59
|
+
function loadRelationships() {
|
|
60
|
+
if (!existsSync(paths.relationships)) {
|
|
61
|
+
return { accounts: {} };
|
|
62
|
+
}
|
|
63
|
+
return JSON.parse(readFileSync(paths.relationships, "utf-8"));
|
|
64
|
+
}
|
|
65
|
+
function saveRelationships(data) {
|
|
66
|
+
ensureDirectories();
|
|
67
|
+
writeFileSync(paths.relationships, JSON.stringify(data, null, 2));
|
|
68
|
+
}
|
|
69
|
+
function updateRelationship(userId, update) {
|
|
70
|
+
const data = loadRelationships();
|
|
71
|
+
const existing = data.accounts[userId];
|
|
72
|
+
if (existing) {
|
|
73
|
+
data.accounts[userId] = {
|
|
74
|
+
...existing,
|
|
75
|
+
...update,
|
|
76
|
+
lastInteraction: (/* @__PURE__ */ new Date()).toISOString(),
|
|
77
|
+
interactionCount: existing.interactionCount + 1
|
|
78
|
+
};
|
|
79
|
+
} else {
|
|
80
|
+
data.accounts[userId] = {
|
|
81
|
+
handle: update.handle,
|
|
82
|
+
firstSeen: (/* @__PURE__ */ new Date()).toISOString(),
|
|
83
|
+
lastInteraction: (/* @__PURE__ */ new Date()).toISOString(),
|
|
84
|
+
interactionCount: 1,
|
|
85
|
+
sentiment: update.sentiment ?? 0,
|
|
86
|
+
tags: update.tags ?? [],
|
|
87
|
+
notes: update.notes ?? [],
|
|
88
|
+
isSpore: update.isSpore ?? false
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
saveRelationships(data);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export {
|
|
95
|
+
logInteraction,
|
|
96
|
+
getInteractions,
|
|
97
|
+
getRecentInteractions,
|
|
98
|
+
loadLearnings,
|
|
99
|
+
saveLearnings,
|
|
100
|
+
addLearning,
|
|
101
|
+
loadRelationships,
|
|
102
|
+
saveRelationships,
|
|
103
|
+
updateRelationship
|
|
104
|
+
};
|
|
105
|
+
//# sourceMappingURL=chunk-V6ZNR2SI.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/memory/index.ts"],"sourcesContent":["import { readFileSync, writeFileSync, appendFileSync, existsSync, readdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { paths, ensureDirectories } from \"../utils/paths.js\";\n\nexport interface InteractionEntry {\n id: string;\n timestamp: string;\n type: \"post\" | \"reply\" | \"like\" | \"retweet\" | \"follow\" | \"mention_received\";\n tweetId?: string;\n targetUserId?: string;\n targetHandle?: string;\n content?: string;\n inReplyTo?: string;\n sentiment?: \"positive\" | \"negative\" | \"neutral\";\n creditsUsed: number;\n success: boolean;\n error?: string;\n}\n\nexport interface Learning {\n id: string;\n timestamp: string;\n content: string;\n source: string;\n tags: string[];\n}\n\nexport interface Relationship {\n handle: string;\n firstSeen: string;\n lastInteraction: string;\n interactionCount: number;\n sentiment: number;\n tags: string[];\n notes: string[];\n isSpore: boolean;\n}\n\nexport interface RelationshipsData {\n accounts: Record<string, Relationship>;\n}\n\nexport interface LearningsData {\n learnings: Learning[];\n}\n\n// --- Interaction Log ---\n\nfunction todayLogPath(): string {\n const date = new Date().toISOString().split(\"T\")[0];\n return join(paths.interactions, `${date}.jsonl`);\n}\n\nexport function logInteraction(entry: InteractionEntry): void {\n ensureDirectories();\n appendFileSync(todayLogPath(), JSON.stringify(entry) + \"\\n\");\n}\n\nexport function getInteractions(date?: string): InteractionEntry[] {\n const targetDate = date ?? new Date().toISOString().split(\"T\")[0];\n const filePath = join(paths.interactions, `${targetDate}.jsonl`);\n\n if (!existsSync(filePath)) return [];\n\n return readFileSync(filePath, \"utf-8\")\n .trim()\n .split(\"\\n\")\n .filter(Boolean)\n .map((line) => JSON.parse(line) as InteractionEntry);\n}\n\nexport function getRecentInteractions(count: number = 20): InteractionEntry[] {\n ensureDirectories();\n const files = readdirSync(paths.interactions)\n .filter((f) => f.endsWith(\".jsonl\"))\n .sort()\n .reverse();\n\n const entries: InteractionEntry[] = [];\n for (const file of files) {\n if (entries.length >= count) break;\n const filePath = join(paths.interactions, file);\n const lines = readFileSync(filePath, \"utf-8\").trim().split(\"\\n\").filter(Boolean);\n for (const line of lines.reverse()) {\n if (entries.length >= count) break;\n entries.push(JSON.parse(line) as InteractionEntry);\n }\n }\n\n return entries;\n}\n\n// --- Learnings ---\n\nexport function loadLearnings(): LearningsData {\n if (!existsSync(paths.learnings)) {\n return { learnings: [] };\n }\n return JSON.parse(readFileSync(paths.learnings, \"utf-8\")) as LearningsData;\n}\n\nexport function saveLearnings(data: LearningsData): void {\n ensureDirectories();\n writeFileSync(paths.learnings, JSON.stringify(data, null, 2));\n}\n\nexport function addLearning(content: string, source: string, tags: string[] = []): void {\n const data = loadLearnings();\n data.learnings.push({\n id: `learn-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,\n timestamp: new Date().toISOString(),\n content,\n source,\n tags,\n });\n saveLearnings(data);\n}\n\n// --- Relationships ---\n\nexport function loadRelationships(): RelationshipsData {\n if (!existsSync(paths.relationships)) {\n return { accounts: {} };\n }\n return JSON.parse(readFileSync(paths.relationships, \"utf-8\")) as RelationshipsData;\n}\n\nexport function saveRelationships(data: RelationshipsData): void {\n ensureDirectories();\n writeFileSync(paths.relationships, JSON.stringify(data, null, 2));\n}\n\nexport function updateRelationship(\n userId: string,\n update: Partial<Relationship> & { handle: string }\n): void {\n const data = loadRelationships();\n const existing = data.accounts[userId];\n\n if (existing) {\n data.accounts[userId] = {\n ...existing,\n ...update,\n lastInteraction: new Date().toISOString(),\n interactionCount: existing.interactionCount + 1,\n };\n } else {\n data.accounts[userId] = {\n handle: update.handle,\n firstSeen: new Date().toISOString(),\n lastInteraction: new Date().toISOString(),\n interactionCount: 1,\n sentiment: update.sentiment ?? 0,\n tags: update.tags ?? [],\n notes: update.notes ?? [],\n isSpore: update.isSpore ?? false,\n };\n }\n\n saveRelationships(data);\n}\n"],"mappings":"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","names":[]}
|