spora 0.3.2 → 0.3.3
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/package.json +1 -1
- package/dist/account-creator-SETL5CGT.js +0 -498
- package/dist/account-creator-SETL5CGT.js.map +0 -1
- package/dist/chunk-DFSYD45Q.js +0 -665
- package/dist/chunk-DFSYD45Q.js.map +0 -1
- package/dist/chunk-FCAK5FYQ.js +0 -127
- package/dist/chunk-FCAK5FYQ.js.map +0 -1
- package/dist/chunk-GJFBWIW3.js +0 -622
- package/dist/chunk-GJFBWIW3.js.map +0 -1
- package/dist/chunk-HERI4RPY.js +0 -156
- package/dist/chunk-HERI4RPY.js.map +0 -1
- package/dist/chunk-J7J557HV.js +0 -47
- package/dist/chunk-J7J557HV.js.map +0 -1
- package/dist/chunk-JWMADEQO.js +0 -57
- package/dist/chunk-JWMADEQO.js.map +0 -1
- package/dist/chunk-LRKBNKMQ.js +0 -79
- package/dist/chunk-LRKBNKMQ.js.map +0 -1
- package/dist/chunk-NLWU5432.js +0 -32
- package/dist/chunk-NLWU5432.js.map +0 -1
- package/dist/chunk-POEDIDM6.js +0 -56
- package/dist/chunk-POEDIDM6.js.map +0 -1
- package/dist/chunk-Q7YS3AIK.js +0 -63
- package/dist/chunk-Q7YS3AIK.js.map +0 -1
- package/dist/chunk-QHFM2YW6.js +0 -159
- package/dist/chunk-QHFM2YW6.js.map +0 -1
- package/dist/chunk-R7PAD4OL.js +0 -44
- package/dist/chunk-R7PAD4OL.js.map +0 -1
- package/dist/chunk-RNVEWVDN.js +0 -129
- package/dist/chunk-RNVEWVDN.js.map +0 -1
- package/dist/chunk-SUFTVQME.js +0 -82
- package/dist/chunk-SUFTVQME.js.map +0 -1
- package/dist/chunk-SXMDYUK3.js +0 -80
- package/dist/chunk-SXMDYUK3.js.map +0 -1
- package/dist/chunk-YZ7RWJ6Z.js +0 -262
- package/dist/chunk-YZ7RWJ6Z.js.map +0 -1
- package/dist/cli.js +0 -654
- package/dist/cli.js.map +0 -1
- package/dist/client-23THPNVL.js +0 -382
- package/dist/client-23THPNVL.js.map +0 -1
- package/dist/client-NVI3ZD4G.js +0 -411
- package/dist/client-NVI3ZD4G.js.map +0 -1
- package/dist/colony-J4EZQI37.js +0 -229
- package/dist/colony-J4EZQI37.js.map +0 -1
- package/dist/config-QRBOL4NX.js +0 -14
- package/dist/config-QRBOL4NX.js.map +0 -1
- package/dist/crypto-ZVWJLD2J.js +0 -14
- package/dist/crypto-ZVWJLD2J.js.map +0 -1
- package/dist/decision-engine-WBD36PZI.js +0 -19
- package/dist/decision-engine-WBD36PZI.js.map +0 -1
- package/dist/goals-IM4AEHS4.js +0 -12
- package/dist/goals-IM4AEHS4.js.map +0 -1
- package/dist/heartbeat-35HVB5PB.js +0 -317
- package/dist/heartbeat-35HVB5PB.js.map +0 -1
- package/dist/identity-LN2R4KJU.js +0 -26
- package/dist/identity-LN2R4KJU.js.map +0 -1
- package/dist/image-search-SZVMGWLN.js +0 -45
- package/dist/image-search-SZVMGWLN.js.map +0 -1
- package/dist/init-ANGLSI2L.js +0 -403
- package/dist/init-ANGLSI2L.js.map +0 -1
- package/dist/llm-MHZG2VHU.js +0 -16
- package/dist/llm-MHZG2VHU.js.map +0 -1
- package/dist/mcp-server.js +0 -773
- package/dist/mcp-server.js.map +0 -1
- package/dist/memory-J6AYZ5Y2.js +0 -26
- package/dist/memory-J6AYZ5Y2.js.map +0 -1
- package/dist/memory-JMXU3UXR.js +0 -26
- package/dist/memory-JMXU3UXR.js.map +0 -1
- package/dist/paths-KXOWF2B2.js +0 -13
- package/dist/paths-KXOWF2B2.js.map +0 -1
- package/dist/performance-7G6R6ELJ.js +0 -18
- package/dist/performance-7G6R6ELJ.js.map +0 -1
- package/dist/prompt-builder-NSU4IFPB.js +0 -28
- package/dist/prompt-builder-NSU4IFPB.js.map +0 -1
- package/dist/queue-MLRTMJRE.js +0 -14
- package/dist/queue-MLRTMJRE.js.map +0 -1
- package/dist/strategy-TOVFBIZQ.js +0 -12
- package/dist/strategy-TOVFBIZQ.js.map +0 -1
- package/dist/web-chat/chat.html +0 -1343
- package/dist/web-chat/logo.png +0 -0
- package/dist/web-chat-N2AYUWT7.js +0 -802
- package/dist/web-chat-N2AYUWT7.js.map +0 -1
- package/dist/x-client-HUXCQOAW.js +0 -12
- package/dist/x-client-HUXCQOAW.js.map +0 -1
package/dist/colony-J4EZQI37.js
DELETED
|
@@ -1,229 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
addColonyEntry,
|
|
3
|
-
addOrUpdatePlan,
|
|
4
|
-
addPlanParticipant,
|
|
5
|
-
getActivePlans,
|
|
6
|
-
getTodayEntries,
|
|
7
|
-
loadColonyMemory,
|
|
8
|
-
renderColonyBriefing,
|
|
9
|
-
saveColonyMemory
|
|
10
|
-
} from "./chunk-HERI4RPY.js";
|
|
11
|
-
import {
|
|
12
|
-
getXClient
|
|
13
|
-
} from "./chunk-NLWU5432.js";
|
|
14
|
-
import "./chunk-SXMDYUK3.js";
|
|
15
|
-
import {
|
|
16
|
-
loadIdentity
|
|
17
|
-
} from "./chunk-GJFBWIW3.js";
|
|
18
|
-
import {
|
|
19
|
-
logger
|
|
20
|
-
} from "./chunk-J7J557HV.js";
|
|
21
|
-
import "./chunk-Q7YS3AIK.js";
|
|
22
|
-
|
|
23
|
-
// src/colony/index.ts
|
|
24
|
-
var COLONY_TAG = "#SporaColony";
|
|
25
|
-
async function colonyCheckin(message) {
|
|
26
|
-
const identity = loadIdentity();
|
|
27
|
-
if (!identity.colony.joined) {
|
|
28
|
-
return {
|
|
29
|
-
posted: false,
|
|
30
|
-
message: "Not a Colony member. Join during Spore creation.",
|
|
31
|
-
colonyMemory: loadColonyMemory(),
|
|
32
|
-
communityFeed: [],
|
|
33
|
-
discoveredSpores: []
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
const client = await getXClient();
|
|
37
|
-
const result = {
|
|
38
|
-
posted: false,
|
|
39
|
-
colonyMemory: loadColonyMemory(),
|
|
40
|
-
communityFeed: [],
|
|
41
|
-
discoveredSpores: []
|
|
42
|
-
};
|
|
43
|
-
try {
|
|
44
|
-
const feed = await client.searchTweets(COLONY_TAG, { count: 30 });
|
|
45
|
-
result.communityFeed = feed;
|
|
46
|
-
const memory = loadColonyMemory();
|
|
47
|
-
const sporeHandles = /* @__PURE__ */ new Set();
|
|
48
|
-
for (const tweet of feed) {
|
|
49
|
-
if (tweet.authorHandle === identity.handle) continue;
|
|
50
|
-
sporeHandles.add(tweet.authorHandle);
|
|
51
|
-
const text = tweet.text;
|
|
52
|
-
if (text.includes("[PLAN]")) {
|
|
53
|
-
const planContent = text.replace(COLONY_TAG, "").replace("[PLAN]", "").trim();
|
|
54
|
-
const existingPlan = memory.activePlans.find(
|
|
55
|
-
(p) => p.proposedBy === tweet.authorHandle && p.description === planContent
|
|
56
|
-
);
|
|
57
|
-
if (!existingPlan) {
|
|
58
|
-
memory.activePlans.push({
|
|
59
|
-
id: tweet.id,
|
|
60
|
-
proposedBy: tweet.authorHandle,
|
|
61
|
-
description: planContent,
|
|
62
|
-
proposedAt: tweet.createdAt,
|
|
63
|
-
participants: [tweet.authorHandle],
|
|
64
|
-
status: "active",
|
|
65
|
-
reports: []
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
} else if (text.includes("[JOIN:")) {
|
|
69
|
-
const planId = text.match(/\[JOIN:([^\]]+)\]/)?.[1];
|
|
70
|
-
if (planId) {
|
|
71
|
-
const plan = memory.activePlans.find((p) => p.id === planId);
|
|
72
|
-
if (plan && !plan.participants.includes(tweet.authorHandle)) {
|
|
73
|
-
plan.participants.push(tweet.authorHandle);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
} else if (text.includes("[STATUS]")) {
|
|
77
|
-
const statusContent = text.replace(COLONY_TAG, "").replace("[STATUS]", "").trim();
|
|
78
|
-
const exists = memory.entries.some(
|
|
79
|
-
(e) => e.handle === tweet.authorHandle && e.content === statusContent
|
|
80
|
-
);
|
|
81
|
-
if (!exists) {
|
|
82
|
-
memory.entries.push({
|
|
83
|
-
handle: tweet.authorHandle,
|
|
84
|
-
content: statusContent,
|
|
85
|
-
timestamp: tweet.createdAt,
|
|
86
|
-
type: "status"
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
} else {
|
|
90
|
-
const chatterContent = text.replace(COLONY_TAG, "").trim();
|
|
91
|
-
const exists = memory.entries.some(
|
|
92
|
-
(e) => e.handle === tweet.authorHandle && e.content === chatterContent
|
|
93
|
-
);
|
|
94
|
-
if (!exists) {
|
|
95
|
-
memory.entries.push({
|
|
96
|
-
handle: tweet.authorHandle,
|
|
97
|
-
content: chatterContent,
|
|
98
|
-
timestamp: tweet.createdAt,
|
|
99
|
-
type: "chatter"
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
const cutoff = Date.now() - 48 * 60 * 60 * 1e3;
|
|
105
|
-
for (const plan of memory.activePlans) {
|
|
106
|
-
if (plan.status === "active" && new Date(plan.proposedAt).getTime() < cutoff) {
|
|
107
|
-
plan.status = "expired";
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
memory.lastSynced = (/* @__PURE__ */ new Date()).toISOString();
|
|
111
|
-
saveColonyMemory(memory);
|
|
112
|
-
result.colonyMemory = memory;
|
|
113
|
-
result.discoveredSpores = Array.from(sporeHandles);
|
|
114
|
-
logger.info(
|
|
115
|
-
`Colony sync: ${feed.length} posts, ${result.discoveredSpores.length} Spores, ${memory.activePlans.filter((p) => p.status === "active").length} active plans`
|
|
116
|
-
);
|
|
117
|
-
} catch (error) {
|
|
118
|
-
logger.warn("Failed to read Colony feed", error);
|
|
119
|
-
}
|
|
120
|
-
if (message) {
|
|
121
|
-
try {
|
|
122
|
-
const colonyPost = `${COLONY_TAG} ${message}`;
|
|
123
|
-
const postResult = await client.postTweet(colonyPost.slice(0, 280));
|
|
124
|
-
result.posted = postResult.success;
|
|
125
|
-
result.message = postResult.success ? "Posted to Colony successfully" : `Failed: ${postResult.error}`;
|
|
126
|
-
} catch (error) {
|
|
127
|
-
result.message = `Failed to post: ${error.message}`;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
return result;
|
|
131
|
-
}
|
|
132
|
-
async function proposePlan(description) {
|
|
133
|
-
const identity = loadIdentity();
|
|
134
|
-
if (!identity.colony.joined) {
|
|
135
|
-
return { success: false, error: "Not a Colony member." };
|
|
136
|
-
}
|
|
137
|
-
const client = await getXClient();
|
|
138
|
-
try {
|
|
139
|
-
const postContent = `${COLONY_TAG} [PLAN] ${description}`.slice(0, 280);
|
|
140
|
-
const result = await client.postTweet(postContent);
|
|
141
|
-
if (result.success && result.tweetId) {
|
|
142
|
-
addOrUpdatePlan({
|
|
143
|
-
id: result.tweetId,
|
|
144
|
-
proposedBy: identity.handle,
|
|
145
|
-
description,
|
|
146
|
-
proposedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
147
|
-
participants: [identity.handle],
|
|
148
|
-
status: "active",
|
|
149
|
-
reports: []
|
|
150
|
-
});
|
|
151
|
-
return { success: true, planId: result.tweetId };
|
|
152
|
-
}
|
|
153
|
-
return { success: false, error: result.error };
|
|
154
|
-
} catch (error) {
|
|
155
|
-
return { success: false, error: error.message };
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
async function joinPlan(planId) {
|
|
159
|
-
const identity = loadIdentity();
|
|
160
|
-
if (!identity.colony.joined) {
|
|
161
|
-
return { success: false, error: "Not a Colony member." };
|
|
162
|
-
}
|
|
163
|
-
const memory = loadColonyMemory();
|
|
164
|
-
const plan = memory.activePlans.find((p) => p.id === planId);
|
|
165
|
-
if (!plan) {
|
|
166
|
-
return { success: false, error: `Plan ${planId} not found.` };
|
|
167
|
-
}
|
|
168
|
-
if (plan.participants.includes(identity.handle)) {
|
|
169
|
-
return { success: false, error: "Already joined this plan." };
|
|
170
|
-
}
|
|
171
|
-
const client = await getXClient();
|
|
172
|
-
try {
|
|
173
|
-
const postContent = `${COLONY_TAG} [JOIN:${planId}] I'm in! Joining: ${plan.description}`.slice(0, 280);
|
|
174
|
-
const result = await client.postTweet(postContent);
|
|
175
|
-
if (result.success) {
|
|
176
|
-
addPlanParticipant(planId, identity.handle);
|
|
177
|
-
return { success: true };
|
|
178
|
-
}
|
|
179
|
-
return { success: false, error: result.error };
|
|
180
|
-
} catch (error) {
|
|
181
|
-
return { success: false, error: error.message };
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
async function postStatus(status) {
|
|
185
|
-
const identity = loadIdentity();
|
|
186
|
-
if (!identity.colony.joined) {
|
|
187
|
-
return { success: false, error: "Not a Colony member." };
|
|
188
|
-
}
|
|
189
|
-
const client = await getXClient();
|
|
190
|
-
try {
|
|
191
|
-
const postContent = `${COLONY_TAG} [STATUS] ${status}`.slice(0, 280);
|
|
192
|
-
const result = await client.postTweet(postContent);
|
|
193
|
-
if (result.success) {
|
|
194
|
-
addColonyEntry({
|
|
195
|
-
handle: identity.handle,
|
|
196
|
-
content: status,
|
|
197
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
198
|
-
type: "status"
|
|
199
|
-
});
|
|
200
|
-
return { success: true };
|
|
201
|
-
}
|
|
202
|
-
return { success: false, error: result.error };
|
|
203
|
-
} catch (error) {
|
|
204
|
-
return { success: false, error: error.message };
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
function getColonyMemory() {
|
|
208
|
-
return loadColonyMemory();
|
|
209
|
-
}
|
|
210
|
-
function getActivePlans2() {
|
|
211
|
-
return getActivePlans();
|
|
212
|
-
}
|
|
213
|
-
function getTodaysActivity() {
|
|
214
|
-
return getTodayEntries();
|
|
215
|
-
}
|
|
216
|
-
function getColonyBriefing() {
|
|
217
|
-
return renderColonyBriefing();
|
|
218
|
-
}
|
|
219
|
-
export {
|
|
220
|
-
colonyCheckin,
|
|
221
|
-
getActivePlans2 as getActivePlans,
|
|
222
|
-
getColonyBriefing,
|
|
223
|
-
getColonyMemory,
|
|
224
|
-
getTodaysActivity,
|
|
225
|
-
joinPlan,
|
|
226
|
-
postStatus,
|
|
227
|
-
proposePlan
|
|
228
|
-
};
|
|
229
|
-
//# sourceMappingURL=colony-J4EZQI37.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/colony/index.ts"],"sourcesContent":["import { loadIdentity } from \"../identity/index.js\";\nimport { getXClient } from \"../x-client/index.js\";\nimport { logger } from \"../utils/logger.js\";\nimport {\n loadColonyMemory,\n saveColonyMemory,\n addColonyEntry,\n addOrUpdatePlan,\n addPlanParticipant,\n getRecentEntries,\n getTodayEntries,\n getActivePlans as getActivePlansFromMemory,\n renderColonyBriefing,\n type ColonyMemory,\n type ColonyPlan,\n type ColonyEntry,\n} from \"./memory.js\";\nimport type { Tweet } from \"../x-client/types.js\";\n\n// The Colony is an X Community:\n// https://x.com/i/communities/2018501592421699779\n//\n// Colony memory is a shared, continuously growing state that all Spores read and write.\n// It lives both in the community (as posts) and locally (as a structured cache).\n// When a Spore checks in, it:\n// 1. Reads the community feed to sync colony memory\n// 2. Posts its own status/plans to the community\n// 3. Updates local colony memory cache\n//\n// Memory never resets — it accumulates over time like a real shared consciousness.\n\nconst COLONY_TAG = \"#SporaColony\";\n\n// ========== CHECK-IN ==========\n\nexport interface ColonyCheckinResult {\n posted: boolean;\n message?: string;\n colonyMemory: ColonyMemory;\n communityFeed: Tweet[];\n discoveredSpores: string[];\n}\n\nexport async function colonyCheckin(message?: string): Promise<ColonyCheckinResult> {\n const identity = loadIdentity();\n\n if (!identity.colony.joined) {\n return {\n posted: false,\n message: \"Not a Colony member. Join during Spore creation.\",\n colonyMemory: loadColonyMemory(),\n communityFeed: [],\n discoveredSpores: [],\n };\n }\n\n const client = await getXClient();\n const result: ColonyCheckinResult = {\n posted: false,\n colonyMemory: loadColonyMemory(),\n communityFeed: [],\n discoveredSpores: [],\n };\n\n // Read Colony community feed\n try {\n const feed = await client.searchTweets(COLONY_TAG, { count: 30 });\n result.communityFeed = feed;\n\n const memory = loadColonyMemory();\n const sporeHandles = new Set<string>();\n\n for (const tweet of feed) {\n if (tweet.authorHandle === identity.handle) continue;\n sporeHandles.add(tweet.authorHandle);\n\n const text = tweet.text;\n\n if (text.includes(\"[PLAN]\")) {\n const planContent = text.replace(COLONY_TAG, \"\").replace(\"[PLAN]\", \"\").trim();\n const existingPlan = memory.activePlans.find(\n (p) => p.proposedBy === tweet.authorHandle && p.description === planContent\n );\n if (!existingPlan) {\n memory.activePlans.push({\n id: tweet.id,\n proposedBy: tweet.authorHandle,\n description: planContent,\n proposedAt: tweet.createdAt,\n participants: [tweet.authorHandle],\n status: \"active\",\n reports: [],\n });\n }\n } else if (text.includes(\"[JOIN:\")) {\n const planId = text.match(/\\[JOIN:([^\\]]+)\\]/)?.[1];\n if (planId) {\n const plan = memory.activePlans.find((p) => p.id === planId);\n if (plan && !plan.participants.includes(tweet.authorHandle)) {\n plan.participants.push(tweet.authorHandle);\n }\n }\n } else if (text.includes(\"[STATUS]\")) {\n const statusContent = text.replace(COLONY_TAG, \"\").replace(\"[STATUS]\", \"\").trim();\n const exists = memory.entries.some(\n (e) => e.handle === tweet.authorHandle && e.content === statusContent\n );\n if (!exists) {\n memory.entries.push({\n handle: tweet.authorHandle,\n content: statusContent,\n timestamp: tweet.createdAt,\n type: \"status\",\n });\n }\n } else {\n // General colony chatter\n const chatterContent = text.replace(COLONY_TAG, \"\").trim();\n const exists = memory.entries.some(\n (e) => e.handle === tweet.authorHandle && e.content === chatterContent\n );\n if (!exists) {\n memory.entries.push({\n handle: tweet.authorHandle,\n content: chatterContent,\n timestamp: tweet.createdAt,\n type: \"chatter\",\n });\n }\n }\n }\n\n // Expire old plans (older than 48 hours) but keep them in memory as expired\n const cutoff = Date.now() - 48 * 60 * 60 * 1000;\n for (const plan of memory.activePlans) {\n if (plan.status === \"active\" && new Date(plan.proposedAt).getTime() < cutoff) {\n plan.status = \"expired\";\n }\n }\n\n memory.lastSynced = new Date().toISOString();\n saveColonyMemory(memory);\n\n result.colonyMemory = memory;\n result.discoveredSpores = Array.from(sporeHandles);\n\n logger.info(\n `Colony sync: ${feed.length} posts, ${result.discoveredSpores.length} Spores, ${memory.activePlans.filter((p) => p.status === \"active\").length} active plans`\n );\n } catch (error) {\n logger.warn(\"Failed to read Colony feed\", error);\n }\n\n // Post to Colony if message provided\n if (message) {\n try {\n const colonyPost = `${COLONY_TAG} ${message}`;\n const postResult = await client.postTweet(colonyPost.slice(0, 280));\n result.posted = postResult.success;\n result.message = postResult.success\n ? \"Posted to Colony successfully\"\n : `Failed: ${postResult.error}`;\n } catch (error) {\n result.message = `Failed to post: ${(error as Error).message}`;\n }\n }\n\n return result;\n}\n\n// ========== PLANS ==========\n\nexport async function proposePlan(description: string): Promise<{ success: boolean; planId?: string; error?: string }> {\n const identity = loadIdentity();\n if (!identity.colony.joined) {\n return { success: false, error: \"Not a Colony member.\" };\n }\n\n const client = await getXClient();\n\n try {\n const postContent = `${COLONY_TAG} [PLAN] ${description}`.slice(0, 280);\n const result = await client.postTweet(postContent);\n\n if (result.success && result.tweetId) {\n addOrUpdatePlan({\n id: result.tweetId,\n proposedBy: identity.handle,\n description,\n proposedAt: new Date().toISOString(),\n participants: [identity.handle],\n status: \"active\",\n reports: [],\n });\n\n return { success: true, planId: result.tweetId };\n }\n\n return { success: false, error: result.error };\n } catch (error) {\n return { success: false, error: (error as Error).message };\n }\n}\n\nexport async function joinPlan(planId: string): Promise<{ success: boolean; error?: string }> {\n const identity = loadIdentity();\n if (!identity.colony.joined) {\n return { success: false, error: \"Not a Colony member.\" };\n }\n\n const memory = loadColonyMemory();\n const plan = memory.activePlans.find((p) => p.id === planId);\n if (!plan) {\n return { success: false, error: `Plan ${planId} not found.` };\n }\n\n if (plan.participants.includes(identity.handle)) {\n return { success: false, error: \"Already joined this plan.\" };\n }\n\n const client = await getXClient();\n\n try {\n const postContent = `${COLONY_TAG} [JOIN:${planId}] I'm in! Joining: ${plan.description}`.slice(0, 280);\n const result = await client.postTweet(postContent);\n\n if (result.success) {\n addPlanParticipant(planId, identity.handle);\n return { success: true };\n }\n\n return { success: false, error: result.error };\n } catch (error) {\n return { success: false, error: (error as Error).message };\n }\n}\n\nexport async function postStatus(status: string): Promise<{ success: boolean; error?: string }> {\n const identity = loadIdentity();\n if (!identity.colony.joined) {\n return { success: false, error: \"Not a Colony member.\" };\n }\n\n const client = await getXClient();\n\n try {\n const postContent = `${COLONY_TAG} [STATUS] ${status}`.slice(0, 280);\n const result = await client.postTweet(postContent);\n\n if (result.success) {\n addColonyEntry({\n handle: identity.handle,\n content: status,\n timestamp: new Date().toISOString(),\n type: \"status\",\n });\n return { success: true };\n }\n\n return { success: false, error: result.error };\n } catch (error) {\n return { success: false, error: (error as Error).message };\n }\n}\n\n// ========== READ ==========\n\nexport function getColonyMemory(): ColonyMemory {\n return loadColonyMemory();\n}\n\nexport function getActivePlans(): ColonyPlan[] {\n return getActivePlansFromMemory();\n}\n\nexport function getTodaysActivity(): ColonyEntry[] {\n return getTodayEntries();\n}\n\nexport function getColonyBriefing(): string {\n return renderColonyBriefing();\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AA+BA,IAAM,aAAa;AAYnB,eAAsB,cAAc,SAAgD;AAClF,QAAM,WAAW,aAAa;AAE9B,MAAI,CAAC,SAAS,OAAO,QAAQ;AAC3B,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,cAAc,iBAAiB;AAAA,MAC/B,eAAe,CAAC;AAAA,MAChB,kBAAkB,CAAC;AAAA,IACrB;AAAA,EACF;AAEA,QAAM,SAAS,MAAM,WAAW;AAChC,QAAM,SAA8B;AAAA,IAClC,QAAQ;AAAA,IACR,cAAc,iBAAiB;AAAA,IAC/B,eAAe,CAAC;AAAA,IAChB,kBAAkB,CAAC;AAAA,EACrB;AAGA,MAAI;AACF,UAAM,OAAO,MAAM,OAAO,aAAa,YAAY,EAAE,OAAO,GAAG,CAAC;AAChE,WAAO,gBAAgB;AAEvB,UAAM,SAAS,iBAAiB;AAChC,UAAM,eAAe,oBAAI,IAAY;AAErC,eAAW,SAAS,MAAM;AACxB,UAAI,MAAM,iBAAiB,SAAS,OAAQ;AAC5C,mBAAa,IAAI,MAAM,YAAY;AAEnC,YAAM,OAAO,MAAM;AAEnB,UAAI,KAAK,SAAS,QAAQ,GAAG;AAC3B,cAAM,cAAc,KAAK,QAAQ,YAAY,EAAE,EAAE,QAAQ,UAAU,EAAE,EAAE,KAAK;AAC5E,cAAM,eAAe,OAAO,YAAY;AAAA,UACtC,CAAC,MAAM,EAAE,eAAe,MAAM,gBAAgB,EAAE,gBAAgB;AAAA,QAClE;AACA,YAAI,CAAC,cAAc;AACjB,iBAAO,YAAY,KAAK;AAAA,YACtB,IAAI,MAAM;AAAA,YACV,YAAY,MAAM;AAAA,YAClB,aAAa;AAAA,YACb,YAAY,MAAM;AAAA,YAClB,cAAc,CAAC,MAAM,YAAY;AAAA,YACjC,QAAQ;AAAA,YACR,SAAS,CAAC;AAAA,UACZ,CAAC;AAAA,QACH;AAAA,MACF,WAAW,KAAK,SAAS,QAAQ,GAAG;AAClC,cAAM,SAAS,KAAK,MAAM,mBAAmB,IAAI,CAAC;AAClD,YAAI,QAAQ;AACV,gBAAM,OAAO,OAAO,YAAY,KAAK,CAAC,MAAM,EAAE,OAAO,MAAM;AAC3D,cAAI,QAAQ,CAAC,KAAK,aAAa,SAAS,MAAM,YAAY,GAAG;AAC3D,iBAAK,aAAa,KAAK,MAAM,YAAY;AAAA,UAC3C;AAAA,QACF;AAAA,MACF,WAAW,KAAK,SAAS,UAAU,GAAG;AACpC,cAAM,gBAAgB,KAAK,QAAQ,YAAY,EAAE,EAAE,QAAQ,YAAY,EAAE,EAAE,KAAK;AAChF,cAAM,SAAS,OAAO,QAAQ;AAAA,UAC5B,CAAC,MAAM,EAAE,WAAW,MAAM,gBAAgB,EAAE,YAAY;AAAA,QAC1D;AACA,YAAI,CAAC,QAAQ;AACX,iBAAO,QAAQ,KAAK;AAAA,YAClB,QAAQ,MAAM;AAAA,YACd,SAAS;AAAA,YACT,WAAW,MAAM;AAAA,YACjB,MAAM;AAAA,UACR,CAAC;AAAA,QACH;AAAA,MACF,OAAO;AAEL,cAAM,iBAAiB,KAAK,QAAQ,YAAY,EAAE,EAAE,KAAK;AACzD,cAAM,SAAS,OAAO,QAAQ;AAAA,UAC5B,CAAC,MAAM,EAAE,WAAW,MAAM,gBAAgB,EAAE,YAAY;AAAA,QAC1D;AACA,YAAI,CAAC,QAAQ;AACX,iBAAO,QAAQ,KAAK;AAAA,YAClB,QAAQ,MAAM;AAAA,YACd,SAAS;AAAA,YACT,WAAW,MAAM;AAAA,YACjB,MAAM;AAAA,UACR,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAGA,UAAM,SAAS,KAAK,IAAI,IAAI,KAAK,KAAK,KAAK;AAC3C,eAAW,QAAQ,OAAO,aAAa;AACrC,UAAI,KAAK,WAAW,YAAY,IAAI,KAAK,KAAK,UAAU,EAAE,QAAQ,IAAI,QAAQ;AAC5E,aAAK,SAAS;AAAA,MAChB;AAAA,IACF;AAEA,WAAO,cAAa,oBAAI,KAAK,GAAE,YAAY;AAC3C,qBAAiB,MAAM;AAEvB,WAAO,eAAe;AACtB,WAAO,mBAAmB,MAAM,KAAK,YAAY;AAEjD,WAAO;AAAA,MACL,gBAAgB,KAAK,MAAM,WAAW,OAAO,iBAAiB,MAAM,YAAY,OAAO,YAAY,OAAO,CAAC,MAAM,EAAE,WAAW,QAAQ,EAAE,MAAM;AAAA,IAChJ;AAAA,EACF,SAAS,OAAO;AACd,WAAO,KAAK,8BAA8B,KAAK;AAAA,EACjD;AAGA,MAAI,SAAS;AACX,QAAI;AACF,YAAM,aAAa,GAAG,UAAU,IAAI,OAAO;AAC3C,YAAM,aAAa,MAAM,OAAO,UAAU,WAAW,MAAM,GAAG,GAAG,CAAC;AAClE,aAAO,SAAS,WAAW;AAC3B,aAAO,UAAU,WAAW,UACxB,kCACA,WAAW,WAAW,KAAK;AAAA,IACjC,SAAS,OAAO;AACd,aAAO,UAAU,mBAAoB,MAAgB,OAAO;AAAA,IAC9D;AAAA,EACF;AAEA,SAAO;AACT;AAIA,eAAsB,YAAY,aAAqF;AACrH,QAAM,WAAW,aAAa;AAC9B,MAAI,CAAC,SAAS,OAAO,QAAQ;AAC3B,WAAO,EAAE,SAAS,OAAO,OAAO,uBAAuB;AAAA,EACzD;AAEA,QAAM,SAAS,MAAM,WAAW;AAEhC,MAAI;AACF,UAAM,cAAc,GAAG,UAAU,WAAW,WAAW,GAAG,MAAM,GAAG,GAAG;AACtE,UAAM,SAAS,MAAM,OAAO,UAAU,WAAW;AAEjD,QAAI,OAAO,WAAW,OAAO,SAAS;AACpC,sBAAgB;AAAA,QACd,IAAI,OAAO;AAAA,QACX,YAAY,SAAS;AAAA,QACrB;AAAA,QACA,aAAY,oBAAI,KAAK,GAAE,YAAY;AAAA,QACnC,cAAc,CAAC,SAAS,MAAM;AAAA,QAC9B,QAAQ;AAAA,QACR,SAAS,CAAC;AAAA,MACZ,CAAC;AAED,aAAO,EAAE,SAAS,MAAM,QAAQ,OAAO,QAAQ;AAAA,IACjD;AAEA,WAAO,EAAE,SAAS,OAAO,OAAO,OAAO,MAAM;AAAA,EAC/C,SAAS,OAAO;AACd,WAAO,EAAE,SAAS,OAAO,OAAQ,MAAgB,QAAQ;AAAA,EAC3D;AACF;AAEA,eAAsB,SAAS,QAA+D;AAC5F,QAAM,WAAW,aAAa;AAC9B,MAAI,CAAC,SAAS,OAAO,QAAQ;AAC3B,WAAO,EAAE,SAAS,OAAO,OAAO,uBAAuB;AAAA,EACzD;AAEA,QAAM,SAAS,iBAAiB;AAChC,QAAM,OAAO,OAAO,YAAY,KAAK,CAAC,MAAM,EAAE,OAAO,MAAM;AAC3D,MAAI,CAAC,MAAM;AACT,WAAO,EAAE,SAAS,OAAO,OAAO,QAAQ,MAAM,cAAc;AAAA,EAC9D;AAEA,MAAI,KAAK,aAAa,SAAS,SAAS,MAAM,GAAG;AAC/C,WAAO,EAAE,SAAS,OAAO,OAAO,4BAA4B;AAAA,EAC9D;AAEA,QAAM,SAAS,MAAM,WAAW;AAEhC,MAAI;AACF,UAAM,cAAc,GAAG,UAAU,UAAU,MAAM,sBAAsB,KAAK,WAAW,GAAG,MAAM,GAAG,GAAG;AACtG,UAAM,SAAS,MAAM,OAAO,UAAU,WAAW;AAEjD,QAAI,OAAO,SAAS;AAClB,yBAAmB,QAAQ,SAAS,MAAM;AAC1C,aAAO,EAAE,SAAS,KAAK;AAAA,IACzB;AAEA,WAAO,EAAE,SAAS,OAAO,OAAO,OAAO,MAAM;AAAA,EAC/C,SAAS,OAAO;AACd,WAAO,EAAE,SAAS,OAAO,OAAQ,MAAgB,QAAQ;AAAA,EAC3D;AACF;AAEA,eAAsB,WAAW,QAA+D;AAC9F,QAAM,WAAW,aAAa;AAC9B,MAAI,CAAC,SAAS,OAAO,QAAQ;AAC3B,WAAO,EAAE,SAAS,OAAO,OAAO,uBAAuB;AAAA,EACzD;AAEA,QAAM,SAAS,MAAM,WAAW;AAEhC,MAAI;AACF,UAAM,cAAc,GAAG,UAAU,aAAa,MAAM,GAAG,MAAM,GAAG,GAAG;AACnE,UAAM,SAAS,MAAM,OAAO,UAAU,WAAW;AAEjD,QAAI,OAAO,SAAS;AAClB,qBAAe;AAAA,QACb,QAAQ,SAAS;AAAA,QACjB,SAAS;AAAA,QACT,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,QAClC,MAAM;AAAA,MACR,CAAC;AACD,aAAO,EAAE,SAAS,KAAK;AAAA,IACzB;AAEA,WAAO,EAAE,SAAS,OAAO,OAAO,OAAO,MAAM;AAAA,EAC/C,SAAS,OAAO;AACd,WAAO,EAAE,SAAS,OAAO,OAAQ,MAAgB,QAAQ;AAAA,EAC3D;AACF;AAIO,SAAS,kBAAgC;AAC9C,SAAO,iBAAiB;AAC1B;AAEO,SAASA,kBAA+B;AAC7C,SAAO,eAAyB;AAClC;AAEO,SAAS,oBAAmC;AACjD,SAAO,gBAAgB;AACzB;AAEO,SAAS,oBAA4B;AAC1C,SAAO,qBAAqB;AAC9B;","names":["getActivePlans"]}
|
package/dist/config-QRBOL4NX.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ConfigSchema,
|
|
3
|
-
createDefaultConfig,
|
|
4
|
-
loadConfig,
|
|
5
|
-
saveConfig
|
|
6
|
-
} from "./chunk-SXMDYUK3.js";
|
|
7
|
-
import "./chunk-Q7YS3AIK.js";
|
|
8
|
-
export {
|
|
9
|
-
ConfigSchema,
|
|
10
|
-
createDefaultConfig,
|
|
11
|
-
loadConfig,
|
|
12
|
-
saveConfig
|
|
13
|
-
};
|
|
14
|
-
//# sourceMappingURL=config-QRBOL4NX.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
package/dist/crypto-ZVWJLD2J.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
decrypt,
|
|
3
|
-
encrypt,
|
|
4
|
-
loadCredentials,
|
|
5
|
-
saveCredentials
|
|
6
|
-
} from "./chunk-POEDIDM6.js";
|
|
7
|
-
import "./chunk-Q7YS3AIK.js";
|
|
8
|
-
export {
|
|
9
|
-
decrypt,
|
|
10
|
-
encrypt,
|
|
11
|
-
loadCredentials,
|
|
12
|
-
saveCredentials
|
|
13
|
-
};
|
|
14
|
-
//# sourceMappingURL=crypto-ZVWJLD2J.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
executeAction,
|
|
3
|
-
executeActions,
|
|
4
|
-
parseActions
|
|
5
|
-
} from "./chunk-YZ7RWJ6Z.js";
|
|
6
|
-
import "./chunk-NLWU5432.js";
|
|
7
|
-
import "./chunk-FCAK5FYQ.js";
|
|
8
|
-
import "./chunk-QHFM2YW6.js";
|
|
9
|
-
import "./chunk-SXMDYUK3.js";
|
|
10
|
-
import "./chunk-GJFBWIW3.js";
|
|
11
|
-
import "./chunk-J7J557HV.js";
|
|
12
|
-
import "./chunk-RNVEWVDN.js";
|
|
13
|
-
import "./chunk-Q7YS3AIK.js";
|
|
14
|
-
export {
|
|
15
|
-
executeAction,
|
|
16
|
-
executeActions,
|
|
17
|
-
parseActions
|
|
18
|
-
};
|
|
19
|
-
//# sourceMappingURL=decision-engine-WBD36PZI.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
package/dist/goals-IM4AEHS4.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -1,317 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
executeActions,
|
|
3
|
-
parseActions
|
|
4
|
-
} from "./chunk-YZ7RWJ6Z.js";
|
|
5
|
-
import {
|
|
6
|
-
buildHeartbeatUserMessage,
|
|
7
|
-
buildReflectionPrompt,
|
|
8
|
-
buildSystemPrompt,
|
|
9
|
-
parseReflection
|
|
10
|
-
} from "./chunk-DFSYD45Q.js";
|
|
11
|
-
import {
|
|
12
|
-
generateResponse
|
|
13
|
-
} from "./chunk-SUFTVQME.js";
|
|
14
|
-
import {
|
|
15
|
-
loadStrategy,
|
|
16
|
-
saveStrategy
|
|
17
|
-
} from "./chunk-LRKBNKMQ.js";
|
|
18
|
-
import "./chunk-R7PAD4OL.js";
|
|
19
|
-
import "./chunk-JWMADEQO.js";
|
|
20
|
-
import {
|
|
21
|
-
getXClient
|
|
22
|
-
} from "./chunk-NLWU5432.js";
|
|
23
|
-
import {
|
|
24
|
-
getActiveTrackedPosts,
|
|
25
|
-
getPerformanceSummary,
|
|
26
|
-
retireOldPosts,
|
|
27
|
-
updatePostMetrics,
|
|
28
|
-
updateSelfMetrics
|
|
29
|
-
} from "./chunk-FCAK5FYQ.js";
|
|
30
|
-
import {
|
|
31
|
-
flushQueue
|
|
32
|
-
} from "./chunk-QHFM2YW6.js";
|
|
33
|
-
import {
|
|
34
|
-
loadConfig
|
|
35
|
-
} from "./chunk-SXMDYUK3.js";
|
|
36
|
-
import {
|
|
37
|
-
loadIdentity
|
|
38
|
-
} from "./chunk-GJFBWIW3.js";
|
|
39
|
-
import {
|
|
40
|
-
logger
|
|
41
|
-
} from "./chunk-J7J557HV.js";
|
|
42
|
-
import {
|
|
43
|
-
addLearning
|
|
44
|
-
} from "./chunk-RNVEWVDN.js";
|
|
45
|
-
import {
|
|
46
|
-
paths
|
|
47
|
-
} from "./chunk-Q7YS3AIK.js";
|
|
48
|
-
|
|
49
|
-
// src/runtime/heartbeat.ts
|
|
50
|
-
import { existsSync, unlinkSync, writeFileSync, readFileSync } from "fs";
|
|
51
|
-
var running = false;
|
|
52
|
-
var lastMentionsSinceId;
|
|
53
|
-
function isRunning() {
|
|
54
|
-
return running;
|
|
55
|
-
}
|
|
56
|
-
function requestStop() {
|
|
57
|
-
writeFileSync(paths.stopSignal, "stop");
|
|
58
|
-
logger.info("Stop signal sent.");
|
|
59
|
-
}
|
|
60
|
-
function shouldStop() {
|
|
61
|
-
if (existsSync(paths.stopSignal)) {
|
|
62
|
-
unlinkSync(paths.stopSignal);
|
|
63
|
-
return true;
|
|
64
|
-
}
|
|
65
|
-
return false;
|
|
66
|
-
}
|
|
67
|
-
function writePid() {
|
|
68
|
-
writeFileSync(paths.runtimePid, String(process.pid));
|
|
69
|
-
}
|
|
70
|
-
function clearPid() {
|
|
71
|
-
if (existsSync(paths.runtimePid)) {
|
|
72
|
-
unlinkSync(paths.runtimePid);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
function getRunningPid() {
|
|
76
|
-
if (!existsSync(paths.runtimePid)) return null;
|
|
77
|
-
const pid = parseInt(readFileSync(paths.runtimePid, "utf-8").trim(), 10);
|
|
78
|
-
if (isNaN(pid)) return null;
|
|
79
|
-
try {
|
|
80
|
-
process.kill(pid, 0);
|
|
81
|
-
return pid;
|
|
82
|
-
} catch {
|
|
83
|
-
clearPid();
|
|
84
|
-
return null;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
async function startHeartbeatLoop() {
|
|
88
|
-
const existingPid = getRunningPid();
|
|
89
|
-
if (existingPid) {
|
|
90
|
-
throw new Error(`Spora is already running (PID ${existingPid}). Run \`spora stop\` first.`);
|
|
91
|
-
}
|
|
92
|
-
running = true;
|
|
93
|
-
writePid();
|
|
94
|
-
const config = loadConfig();
|
|
95
|
-
const intervalMs = config.runtime?.heartbeatIntervalMs ?? 6e4;
|
|
96
|
-
const maxActions = config.runtime?.actionsPerHeartbeat ?? 3;
|
|
97
|
-
logger.info(`Spora agent starting. Heartbeat interval: ${intervalMs / 1e3}s, max actions: ${maxActions}`);
|
|
98
|
-
console.log(`
|
|
99
|
-
Spora agent is running (PID ${process.pid})`);
|
|
100
|
-
console.log(`Heartbeat every ${Math.round(intervalMs / 6e4)} minutes`);
|
|
101
|
-
console.log(`Press Ctrl+C or run \`spora stop\` to stop.
|
|
102
|
-
`);
|
|
103
|
-
const shutdown = () => {
|
|
104
|
-
logger.info("Shutting down...");
|
|
105
|
-
running = false;
|
|
106
|
-
clearPid();
|
|
107
|
-
process.exit(0);
|
|
108
|
-
};
|
|
109
|
-
process.on("SIGINT", shutdown);
|
|
110
|
-
process.on("SIGTERM", shutdown);
|
|
111
|
-
if (existsSync(paths.stopSignal)) {
|
|
112
|
-
unlinkSync(paths.stopSignal);
|
|
113
|
-
}
|
|
114
|
-
let heartbeatCount = 0;
|
|
115
|
-
while (running) {
|
|
116
|
-
heartbeatCount++;
|
|
117
|
-
logger.info(`=== Heartbeat #${heartbeatCount} ===`);
|
|
118
|
-
try {
|
|
119
|
-
await runHeartbeat(maxActions, intervalMs, heartbeatCount);
|
|
120
|
-
} catch (error) {
|
|
121
|
-
logger.error("Heartbeat error", error);
|
|
122
|
-
console.error(`Heartbeat #${heartbeatCount} failed: ${error.message}`);
|
|
123
|
-
}
|
|
124
|
-
if (shouldStop()) {
|
|
125
|
-
logger.info("Stop signal received.");
|
|
126
|
-
break;
|
|
127
|
-
}
|
|
128
|
-
const jitter = Math.floor(Math.random() * intervalMs * 0.3);
|
|
129
|
-
const sleepMs = intervalMs + jitter;
|
|
130
|
-
logger.info(`Sleeping ${Math.round(sleepMs / 1e3)}s until next heartbeat...`);
|
|
131
|
-
const chunkMs = 1e4;
|
|
132
|
-
let slept = 0;
|
|
133
|
-
while (slept < sleepMs && running) {
|
|
134
|
-
await new Promise((r) => setTimeout(r, Math.min(chunkMs, sleepMs - slept)));
|
|
135
|
-
slept += chunkMs;
|
|
136
|
-
if (shouldStop()) {
|
|
137
|
-
running = false;
|
|
138
|
-
break;
|
|
139
|
-
}
|
|
140
|
-
try {
|
|
141
|
-
const flushed = await flushQueue();
|
|
142
|
-
if (flushed.posted > 0) {
|
|
143
|
-
logger.info(`Flushed ${flushed.posted} scheduled post(s) during sleep`);
|
|
144
|
-
}
|
|
145
|
-
} catch {
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
clearPid();
|
|
150
|
-
logger.info("Spora agent stopped.");
|
|
151
|
-
console.log("\nSpora agent stopped.");
|
|
152
|
-
}
|
|
153
|
-
async function runHeartbeat(maxActions, intervalMs, heartbeatCount = 1) {
|
|
154
|
-
logger.info("Checking queue...");
|
|
155
|
-
try {
|
|
156
|
-
const flushed = await flushQueue();
|
|
157
|
-
if (flushed.posted > 0) {
|
|
158
|
-
logger.info(`Flushed ${flushed.posted} queued posts.`);
|
|
159
|
-
}
|
|
160
|
-
} catch (error) {
|
|
161
|
-
logger.warn(`Queue flush failed: ${error.message}`);
|
|
162
|
-
}
|
|
163
|
-
const client = await getXClient();
|
|
164
|
-
let ownHandle;
|
|
165
|
-
if ("getAuthenticatedHandle" in client) {
|
|
166
|
-
try {
|
|
167
|
-
ownHandle = await client.getAuthenticatedHandle();
|
|
168
|
-
} catch {
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
logger.info("Checking post performance...");
|
|
172
|
-
try {
|
|
173
|
-
retireOldPosts();
|
|
174
|
-
const activePosts = getActiveTrackedPosts();
|
|
175
|
-
for (const post of activePosts.slice(0, 5)) {
|
|
176
|
-
try {
|
|
177
|
-
const tweet = await client.getTweet(post.tweetId);
|
|
178
|
-
if (tweet) {
|
|
179
|
-
updatePostMetrics(post.tweetId, {
|
|
180
|
-
checkedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
181
|
-
likes: tweet.likeCount ?? 0,
|
|
182
|
-
retweets: tweet.retweetCount ?? 0,
|
|
183
|
-
replies: tweet.replyCount ?? 0
|
|
184
|
-
});
|
|
185
|
-
}
|
|
186
|
-
} catch {
|
|
187
|
-
}
|
|
188
|
-
await new Promise((r) => setTimeout(r, 1e3));
|
|
189
|
-
}
|
|
190
|
-
} catch (error) {
|
|
191
|
-
logger.warn(`Performance check failed: ${error.message}`);
|
|
192
|
-
}
|
|
193
|
-
if (heartbeatCount % 6 === 1) {
|
|
194
|
-
logger.info("Checking own profile...");
|
|
195
|
-
try {
|
|
196
|
-
const handle = ownHandle ?? loadIdentity().handle;
|
|
197
|
-
const profile = await client.getProfile(handle);
|
|
198
|
-
updateSelfMetrics({
|
|
199
|
-
checkedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
200
|
-
followers: profile.followersCount,
|
|
201
|
-
following: profile.followingCount,
|
|
202
|
-
totalTweets: profile.tweetCount
|
|
203
|
-
});
|
|
204
|
-
logger.info(`Self: ${profile.followersCount} followers, ${profile.followingCount} following`);
|
|
205
|
-
} catch (error) {
|
|
206
|
-
logger.warn(`Self-check failed: ${error.message}`);
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
logger.info("Reading timeline and mentions...");
|
|
210
|
-
let timeline = [];
|
|
211
|
-
let mentions = [];
|
|
212
|
-
try {
|
|
213
|
-
timeline = await client.getTimeline({ count: 20 });
|
|
214
|
-
if (ownHandle) {
|
|
215
|
-
timeline = timeline.filter((t) => t.authorHandle.toLowerCase() !== ownHandle.toLowerCase());
|
|
216
|
-
}
|
|
217
|
-
} catch (error) {
|
|
218
|
-
logger.warn(`Timeline read failed: ${error.message}`);
|
|
219
|
-
}
|
|
220
|
-
try {
|
|
221
|
-
mentions = await client.getMentions({ count: 10, sinceId: lastMentionsSinceId });
|
|
222
|
-
if (mentions.length > 0) {
|
|
223
|
-
lastMentionsSinceId = mentions[0].id;
|
|
224
|
-
}
|
|
225
|
-
} catch (error) {
|
|
226
|
-
logger.warn(`Mentions read failed: ${error.message}`);
|
|
227
|
-
}
|
|
228
|
-
let discoveryResults = [];
|
|
229
|
-
if (heartbeatCount % 4 === 0) {
|
|
230
|
-
logger.info("Running proactive discovery...");
|
|
231
|
-
try {
|
|
232
|
-
const identity = loadIdentity();
|
|
233
|
-
const strategy = loadStrategy();
|
|
234
|
-
const allTopics = [...identity.topics, ...strategy.currentFocus ?? []];
|
|
235
|
-
if (allTopics.length > 0) {
|
|
236
|
-
const topic = allTopics[Math.floor(Math.random() * allTopics.length)];
|
|
237
|
-
discoveryResults = await client.searchTweets(topic, { count: 10 });
|
|
238
|
-
if (ownHandle) {
|
|
239
|
-
discoveryResults = discoveryResults.filter((t) => t.authorHandle.toLowerCase() !== ownHandle.toLowerCase());
|
|
240
|
-
}
|
|
241
|
-
logger.info(`Discovery for "${topic}": ${discoveryResults.length} results`);
|
|
242
|
-
}
|
|
243
|
-
} catch (error) {
|
|
244
|
-
logger.warn(`Discovery failed: ${error.message}`);
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
const systemPrompt = buildSystemPrompt();
|
|
248
|
-
const userMessage = buildHeartbeatUserMessage(timeline, mentions, intervalMs, discoveryResults);
|
|
249
|
-
logger.info("Asking LLM for decisions...");
|
|
250
|
-
const response = await generateResponse(systemPrompt, userMessage, { temperature: 0.95 });
|
|
251
|
-
const actions = parseActions(response.content);
|
|
252
|
-
if (actions.length === 0) {
|
|
253
|
-
logger.info("LLM returned no actions.");
|
|
254
|
-
return;
|
|
255
|
-
}
|
|
256
|
-
const validTweetIds = /* @__PURE__ */ new Set();
|
|
257
|
-
const tweetMap = /* @__PURE__ */ new Map();
|
|
258
|
-
for (const t of timeline) {
|
|
259
|
-
validTweetIds.add(t.id);
|
|
260
|
-
tweetMap.set(t.id, t);
|
|
261
|
-
}
|
|
262
|
-
for (const t of mentions) {
|
|
263
|
-
validTweetIds.add(t.id);
|
|
264
|
-
tweetMap.set(t.id, t);
|
|
265
|
-
}
|
|
266
|
-
for (const t of discoveryResults) {
|
|
267
|
-
validTweetIds.add(t.id);
|
|
268
|
-
tweetMap.set(t.id, t);
|
|
269
|
-
}
|
|
270
|
-
const validatedActions = actions.filter((a) => {
|
|
271
|
-
if (a.tweetId) {
|
|
272
|
-
const cleanId = a.tweetId.replace(/^tweet:/i, "").trim();
|
|
273
|
-
if (!validTweetIds.has(cleanId)) {
|
|
274
|
-
logger.warn(`Rejected ${a.action}: tweet ID ${cleanId} not in timeline/mentions (likely hallucinated)`);
|
|
275
|
-
return false;
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
return true;
|
|
279
|
-
});
|
|
280
|
-
const limitedActions = validatedActions.slice(0, maxActions);
|
|
281
|
-
logger.info(`Executing ${limitedActions.length} action(s)...`);
|
|
282
|
-
const results = await executeActions(limitedActions, tweetMap);
|
|
283
|
-
for (const result of results) {
|
|
284
|
-
if (result.success) {
|
|
285
|
-
logger.info(` [OK] ${result.action}${result.detail ? `: ${result.detail}` : ""}`);
|
|
286
|
-
} else {
|
|
287
|
-
logger.warn(` [FAIL] ${result.action}: ${result.error}`);
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
logger.info("Reflecting on actions...");
|
|
291
|
-
try {
|
|
292
|
-
const perfSummary = getPerformanceSummary();
|
|
293
|
-
const currentStrategy = loadStrategy();
|
|
294
|
-
const reflectPrompt = buildReflectionPrompt(results, perfSummary, currentStrategy);
|
|
295
|
-
const reflection = await generateResponse(systemPrompt, reflectPrompt, { temperature: 0.7 });
|
|
296
|
-
const reflectionData = parseReflection(reflection.content);
|
|
297
|
-
if (reflectionData.learning) {
|
|
298
|
-
addLearning(reflectionData.learning, "reflection", ["auto-reflect"]);
|
|
299
|
-
logger.info(`Reflection learning: "${reflectionData.learning.slice(0, 60)}..."`);
|
|
300
|
-
}
|
|
301
|
-
if (reflectionData.strategyUpdate) {
|
|
302
|
-
const updated = { ...currentStrategy, ...reflectionData.strategyUpdate, lastUpdated: (/* @__PURE__ */ new Date()).toISOString() };
|
|
303
|
-
saveStrategy(updated);
|
|
304
|
-
logger.info("Strategy updated from reflection.");
|
|
305
|
-
}
|
|
306
|
-
} catch (error) {
|
|
307
|
-
logger.warn(`Reflection failed: ${error.message}`);
|
|
308
|
-
}
|
|
309
|
-
logger.info(`Heartbeat complete. ${results.filter((r) => r.success).length}/${results.length} actions succeeded.`);
|
|
310
|
-
}
|
|
311
|
-
export {
|
|
312
|
-
getRunningPid,
|
|
313
|
-
isRunning,
|
|
314
|
-
requestStop,
|
|
315
|
-
startHeartbeatLoop
|
|
316
|
-
};
|
|
317
|
-
//# sourceMappingURL=heartbeat-35HVB5PB.js.map
|