spora 0.7.4 → 0.7.6
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/autonomy-E3DWYRJM.js +20 -0
- package/dist/{chunk-SUZUJGGW.js → chunk-342ZX72W.js} +4 -4
- package/dist/{chunk-PN5A6MCV.js → chunk-5R4AJZHN.js} +4 -4
- package/dist/{chunk-PN5A6MCV.js.map → chunk-5R4AJZHN.js.map} +1 -1
- package/dist/{chunk-JBYZ7K56.js → chunk-BBXHECZ5.js} +2 -2
- package/dist/{chunk-WN35MRMF.js → chunk-CAWWG3MD.js} +2 -2
- package/dist/chunk-CP6JWCLY.js +171 -0
- package/dist/chunk-CP6JWCLY.js.map +1 -0
- package/dist/{chunk-T7L2L7ZL.js → chunk-D47OFTEK.js} +2 -2
- package/dist/{chunk-Q3YXJ2C6.js → chunk-E5PEY36J.js} +408 -63
- package/dist/chunk-E5PEY36J.js.map +1 -0
- package/dist/chunk-FBHLDOMC.js +2436 -0
- package/dist/chunk-FBHLDOMC.js.map +1 -0
- package/dist/{chunk-M6YOQVSI.js → chunk-IULO3GRE.js} +4 -4
- package/dist/chunk-IULO3GRE.js.map +1 -0
- package/dist/chunk-OTZNHIXT.js +431 -0
- package/dist/chunk-OTZNHIXT.js.map +1 -0
- package/dist/{chunk-NO3NQN67.js → chunk-QYFNAGNI.js} +2 -2
- package/dist/{chunk-YMGJQRKG.js → chunk-RSNEVBEI.js} +2 -2
- package/dist/{chunk-QWEYVDLU.js → chunk-SXNZVKLJ.js} +2 -2
- package/dist/{chunk-MDOFAAZB.js → chunk-ZLSDFYBR.js} +17 -5
- package/dist/chunk-ZLSDFYBR.js.map +1 -0
- package/dist/{chunk-3RYCUGXE.js → chunk-ZWKTKWS6.js} +4 -1
- package/dist/chunk-ZWKTKWS6.js.map +1 -0
- package/dist/cli.js +49 -49
- package/dist/{client-Z5UQWPPI.js → client-AR5ZD6S4.js} +48 -16
- package/dist/client-AR5ZD6S4.js.map +1 -0
- package/dist/{colony-NNX45EAV.js → colony-UGVYALOS.js} +7 -7
- package/dist/{config-FL4VJVKZ.js → config-MU2ODEO3.js} +3 -3
- package/dist/{crypto-B65ZH7KN.js → crypto-GDG5K3ZH.js} +3 -3
- package/dist/{goals-RBKLMILE.js → goals-QWX3A47Y.js} +3 -3
- package/dist/{heartbeat-ZCCOIZGU.js → heartbeat-GVBLNAFM.js} +18 -21
- package/dist/heartbeat-GVBLNAFM.js.map +1 -0
- package/dist/{identity-VDUW4I2K.js → identity-ASHVWIN5.js} +3 -3
- package/dist/{init-SEJPTOOB.js → init-C4OZPGUC.js} +108 -15
- package/dist/init-C4OZPGUC.js.map +1 -0
- package/dist/{llm-OGOYCWBH.js → llm-IJBRQ7O2.js} +5 -5
- package/dist/mcp-server.js +24 -24
- package/dist/{memory-PNW7SX7A.js → memory-AWKIW2KW.js} +3 -3
- package/dist/{memory-OIAH33G2.js → memory-DTSLVSQG.js} +3 -3
- package/dist/{paths-BYR6MEPR.js → paths-4V5OCB5F.js} +2 -2
- package/dist/prompt-builder-NTN4FCBD.js +27 -0
- package/dist/queue-QCGNDHH2.js +14 -0
- package/dist/strategy-R2BMRVJ3.js +19 -0
- package/dist/{web-chat-ZZ65DUID.js → web-chat-2N2RN6J7.js} +23 -28
- package/dist/web-chat-2N2RN6J7.js.map +1 -0
- package/dist/x-client-S2LUVEKV.js +12 -0
- package/package.json +1 -1
- package/dist/autonomy-XUKCAZM3.js +0 -19
- package/dist/chunk-3RYCUGXE.js.map +0 -1
- package/dist/chunk-4LNMA56H.js +0 -57
- package/dist/chunk-4LNMA56H.js.map +0 -1
- package/dist/chunk-EU4FMOKG.js +0 -377
- package/dist/chunk-EU4FMOKG.js.map +0 -1
- package/dist/chunk-M6YOQVSI.js.map +0 -1
- package/dist/chunk-MDOFAAZB.js.map +0 -1
- package/dist/chunk-P6KZIJYL.js +0 -79
- package/dist/chunk-P6KZIJYL.js.map +0 -1
- package/dist/chunk-Q3YXJ2C6.js.map +0 -1
- package/dist/client-Z5UQWPPI.js.map +0 -1
- package/dist/heartbeat-ZCCOIZGU.js.map +0 -1
- package/dist/init-SEJPTOOB.js.map +0 -1
- package/dist/prompt-builder-KJKFCGM7.js +0 -25
- package/dist/queue-2ZBKDFX3.js +0 -14
- package/dist/strategy-Z4JSFHSP.js +0 -12
- package/dist/web-chat-ZZ65DUID.js.map +0 -1
- package/dist/x-client-YG7UCCNI.js +0 -12
- /package/dist/{autonomy-XUKCAZM3.js.map → autonomy-E3DWYRJM.js.map} +0 -0
- /package/dist/{chunk-SUZUJGGW.js.map → chunk-342ZX72W.js.map} +0 -0
- /package/dist/{chunk-JBYZ7K56.js.map → chunk-BBXHECZ5.js.map} +0 -0
- /package/dist/{chunk-WN35MRMF.js.map → chunk-CAWWG3MD.js.map} +0 -0
- /package/dist/{chunk-T7L2L7ZL.js.map → chunk-D47OFTEK.js.map} +0 -0
- /package/dist/{chunk-NO3NQN67.js.map → chunk-QYFNAGNI.js.map} +0 -0
- /package/dist/{chunk-YMGJQRKG.js.map → chunk-RSNEVBEI.js.map} +0 -0
- /package/dist/{chunk-QWEYVDLU.js.map → chunk-SXNZVKLJ.js.map} +0 -0
- /package/dist/{colony-NNX45EAV.js.map → colony-UGVYALOS.js.map} +0 -0
- /package/dist/{config-FL4VJVKZ.js.map → config-MU2ODEO3.js.map} +0 -0
- /package/dist/{crypto-B65ZH7KN.js.map → crypto-GDG5K3ZH.js.map} +0 -0
- /package/dist/{goals-RBKLMILE.js.map → goals-QWX3A47Y.js.map} +0 -0
- /package/dist/{identity-VDUW4I2K.js.map → identity-ASHVWIN5.js.map} +0 -0
- /package/dist/{llm-OGOYCWBH.js.map → llm-IJBRQ7O2.js.map} +0 -0
- /package/dist/{memory-OIAH33G2.js.map → memory-AWKIW2KW.js.map} +0 -0
- /package/dist/{memory-PNW7SX7A.js.map → memory-DTSLVSQG.js.map} +0 -0
- /package/dist/{paths-BYR6MEPR.js.map → paths-4V5OCB5F.js.map} +0 -0
- /package/dist/{prompt-builder-KJKFCGM7.js.map → prompt-builder-NTN4FCBD.js.map} +0 -0
- /package/dist/{queue-2ZBKDFX3.js.map → queue-QCGNDHH2.js.map} +0 -0
- /package/dist/{strategy-Z4JSFHSP.js.map → strategy-R2BMRVJ3.js.map} +0 -0
- /package/dist/{x-client-YG7UCCNI.js.map → x-client-S2LUVEKV.js.map} +0 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import {
|
|
2
|
+
runAutonomyCycle
|
|
3
|
+
} from "./chunk-FBHLDOMC.js";
|
|
4
|
+
import "./chunk-5R4AJZHN.js";
|
|
5
|
+
import "./chunk-ZLSDFYBR.js";
|
|
6
|
+
import "./chunk-E5PEY36J.js";
|
|
7
|
+
import "./chunk-OTZNHIXT.js";
|
|
8
|
+
import "./chunk-CAWWG3MD.js";
|
|
9
|
+
import "./chunk-CP6JWCLY.js";
|
|
10
|
+
import "./chunk-IULO3GRE.js";
|
|
11
|
+
import "./chunk-SXNZVKLJ.js";
|
|
12
|
+
import "./chunk-342ZX72W.js";
|
|
13
|
+
import "./chunk-RSNEVBEI.js";
|
|
14
|
+
import "./chunk-QYFNAGNI.js";
|
|
15
|
+
import "./chunk-BBXHECZ5.js";
|
|
16
|
+
import "./chunk-ZWKTKWS6.js";
|
|
17
|
+
export {
|
|
18
|
+
runAutonomyCycle
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=autonomy-E3DWYRJM.js.map
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
logger
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-RSNEVBEI.js";
|
|
4
4
|
import {
|
|
5
5
|
loadConfig
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-QYFNAGNI.js";
|
|
7
7
|
import {
|
|
8
8
|
paths
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-ZWKTKWS6.js";
|
|
10
10
|
|
|
11
11
|
// src/runtime/llm.ts
|
|
12
12
|
import Anthropic from "@anthropic-ai/sdk";
|
|
@@ -177,4 +177,4 @@ export {
|
|
|
177
177
|
generateResponse,
|
|
178
178
|
chat
|
|
179
179
|
};
|
|
180
|
-
//# sourceMappingURL=chunk-
|
|
180
|
+
//# sourceMappingURL=chunk-342ZX72W.js.map
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
logger
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-RSNEVBEI.js";
|
|
4
4
|
import {
|
|
5
5
|
loadConfig
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-QYFNAGNI.js";
|
|
7
7
|
|
|
8
8
|
// src/x-client/index.ts
|
|
9
9
|
var clientInstance = null;
|
|
@@ -13,7 +13,7 @@ async function getXClient() {
|
|
|
13
13
|
if (config.xMethod !== "api") {
|
|
14
14
|
throw new Error("Only X API mode is supported.");
|
|
15
15
|
}
|
|
16
|
-
const { XApiClient } = await import("./client-
|
|
16
|
+
const { XApiClient } = await import("./client-AR5ZD6S4.js");
|
|
17
17
|
clientInstance = new XApiClient();
|
|
18
18
|
logger.info("X client initialized: API mode");
|
|
19
19
|
return clientInstance;
|
|
@@ -26,4 +26,4 @@ export {
|
|
|
26
26
|
getXClient,
|
|
27
27
|
resetXClient
|
|
28
28
|
};
|
|
29
|
-
//# sourceMappingURL=chunk-
|
|
29
|
+
//# sourceMappingURL=chunk-5R4AJZHN.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/x-client/index.ts"],"sourcesContent":["import { loadConfig } from \"../utils/config.js\";\nimport { logger } from \"../utils/logger.js\";\nimport type { XClientInterface } from \"./types.js\";\n\nlet clientInstance: XClientInterface | null = null;\n\nexport async function getXClient(): Promise<XClientInterface> {\n if (clientInstance) return clientInstance;\n\n const config = loadConfig();\n if (config.xMethod !== \"api\") {\n throw new Error(\"Only X API mode is supported.\");\n }\n\n const { XApiClient } = await import(\"./api/client.js\");\n clientInstance = new XApiClient();\n logger.info(\"X client initialized: API mode\");\n\n return clientInstance;\n}\n\nexport function resetXClient(): void {\n clientInstance = null;\n}\n\nexport type { XClientInterface } from \"./types.js\";\nexport type { Tweet, UserProfile, PostResult, TimelineOptions, SearchOptions } from \"./types.js\";\n"],"mappings":";;;;;;;;AAIA,IAAI,iBAA0C;AAE9C,eAAsB,aAAwC;AAC5D,MAAI,eAAgB,QAAO;AAE3B,QAAM,SAAS,WAAW;AAC1B,MAAI,OAAO,YAAY,OAAO;AAC5B,UAAM,IAAI,MAAM,+BAA+B;AAAA,EACjD;AAEA,QAAM,EAAE,WAAW,IAAI,MAAM,OAAO,sBAAiB;AACrD,mBAAiB,IAAI,WAAW;AAChC,SAAO,KAAK,gCAAgC;AAE5C,SAAO;AACT;AAEO,SAAS,eAAqB;AACnC,mBAAiB;AACnB;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/x-client/index.ts"],"sourcesContent":["import { loadConfig } from \"../utils/config.js\";\nimport { logger } from \"../utils/logger.js\";\nimport type { XClientInterface } from \"./types.js\";\n\nlet clientInstance: XClientInterface | null = null;\n\nexport async function getXClient(): Promise<XClientInterface> {\n if (clientInstance) return clientInstance;\n\n const config = loadConfig();\n if (config.xMethod !== \"api\") {\n throw new Error(\"Only X API mode is supported.\");\n }\n\n const { XApiClient } = await import(\"./api/client.js\");\n clientInstance = new XApiClient();\n logger.info(\"X client initialized: API mode\");\n\n return clientInstance;\n}\n\nexport function resetXClient(): void {\n clientInstance = null;\n}\n\nexport type { XClientInterface } from \"./types.js\";\nexport type { Tweet, UserProfile, PostResult, TimelineOptions, SearchOptions, TweetMetrics } from \"./types.js\";\n"],"mappings":";;;;;;;;AAIA,IAAI,iBAA0C;AAE9C,eAAsB,aAAwC;AAC5D,MAAI,eAAgB,QAAO;AAE3B,QAAM,SAAS,WAAW;AAC1B,MAAI,OAAO,YAAY,OAAO;AAC5B,UAAM,IAAI,MAAM,+BAA+B;AAAA,EACjD;AAEA,QAAM,EAAE,WAAW,IAAI,MAAM,OAAO,sBAAiB;AACrD,mBAAiB,IAAI,WAAW;AAChC,SAAO,KAAK,gCAAgC;AAE5C,SAAO;AACT;AAEO,SAAS,eAAqB;AACnC,mBAAiB;AACnB;","names":[]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ensureDirectories,
|
|
3
3
|
paths
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-ZWKTKWS6.js";
|
|
5
5
|
|
|
6
6
|
// src/memory/index.ts
|
|
7
7
|
import { readFileSync, writeFileSync, appendFileSync, existsSync, readdirSync } from "fs";
|
|
@@ -102,4 +102,4 @@ export {
|
|
|
102
102
|
saveRelationships,
|
|
103
103
|
updateRelationship
|
|
104
104
|
};
|
|
105
|
-
//# sourceMappingURL=chunk-
|
|
105
|
+
//# sourceMappingURL=chunk-BBXHECZ5.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ensureDirectories,
|
|
3
3
|
paths
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-ZWKTKWS6.js";
|
|
5
5
|
|
|
6
6
|
// src/memory/goals.ts
|
|
7
7
|
import { existsSync, readFileSync, writeFileSync } from "fs";
|
|
@@ -41,4 +41,4 @@ export {
|
|
|
41
41
|
saveGoals,
|
|
42
42
|
renderGoalsForPrompt
|
|
43
43
|
};
|
|
44
|
-
//# sourceMappingURL=chunk-
|
|
44
|
+
//# sourceMappingURL=chunk-CAWWG3MD.js.map
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import {
|
|
2
|
+
logger
|
|
3
|
+
} from "./chunk-RSNEVBEI.js";
|
|
4
|
+
import {
|
|
5
|
+
loadConfig,
|
|
6
|
+
saveConfig
|
|
7
|
+
} from "./chunk-QYFNAGNI.js";
|
|
8
|
+
import {
|
|
9
|
+
paths
|
|
10
|
+
} from "./chunk-ZWKTKWS6.js";
|
|
11
|
+
|
|
12
|
+
// src/memory/performance.ts
|
|
13
|
+
import { existsSync, readFileSync, writeFileSync } from "fs";
|
|
14
|
+
function loadPerformance() {
|
|
15
|
+
if (!existsSync(paths.performance)) {
|
|
16
|
+
return { trackedPosts: [], selfMetrics: [] };
|
|
17
|
+
}
|
|
18
|
+
try {
|
|
19
|
+
return JSON.parse(readFileSync(paths.performance, "utf-8"));
|
|
20
|
+
} catch {
|
|
21
|
+
return { trackedPosts: [], selfMetrics: [] };
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function savePerformance(data) {
|
|
25
|
+
writeFileSync(paths.performance, JSON.stringify(data, null, 2));
|
|
26
|
+
}
|
|
27
|
+
function trackPost(tweetId, content, type) {
|
|
28
|
+
const data = loadPerformance();
|
|
29
|
+
if (data.trackedPosts.some((p) => p.tweetId === tweetId)) return;
|
|
30
|
+
data.trackedPosts.push({
|
|
31
|
+
tweetId,
|
|
32
|
+
content,
|
|
33
|
+
type,
|
|
34
|
+
postedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
35
|
+
metrics: [],
|
|
36
|
+
retired: false
|
|
37
|
+
});
|
|
38
|
+
savePerformance(data);
|
|
39
|
+
}
|
|
40
|
+
function getActiveTrackedPosts() {
|
|
41
|
+
const data = loadPerformance();
|
|
42
|
+
return data.trackedPosts.filter((p) => !p.retired);
|
|
43
|
+
}
|
|
44
|
+
function updatePostMetrics(tweetId, metric) {
|
|
45
|
+
const data = loadPerformance();
|
|
46
|
+
const post = data.trackedPosts.find((p) => p.tweetId === tweetId);
|
|
47
|
+
if (!post) return;
|
|
48
|
+
post.metrics.push(metric);
|
|
49
|
+
savePerformance(data);
|
|
50
|
+
}
|
|
51
|
+
function retireOldPosts() {
|
|
52
|
+
const data = loadPerformance();
|
|
53
|
+
const cutoff = Date.now() - 72 * 60 * 60 * 1e3;
|
|
54
|
+
let changed = false;
|
|
55
|
+
for (const post of data.trackedPosts) {
|
|
56
|
+
if (!post.retired && new Date(post.postedAt).getTime() < cutoff) {
|
|
57
|
+
post.retired = true;
|
|
58
|
+
changed = true;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
const pruneCutoff = Date.now() - 30 * 24 * 60 * 60 * 1e3;
|
|
62
|
+
const before = data.trackedPosts.length;
|
|
63
|
+
data.trackedPosts = data.trackedPosts.filter(
|
|
64
|
+
(p) => !p.retired || new Date(p.postedAt).getTime() > pruneCutoff
|
|
65
|
+
);
|
|
66
|
+
if (data.trackedPosts.length !== before) changed = true;
|
|
67
|
+
if (changed) savePerformance(data);
|
|
68
|
+
}
|
|
69
|
+
function getPerformanceSummary() {
|
|
70
|
+
const data = loadPerformance();
|
|
71
|
+
const lines = [];
|
|
72
|
+
const oneDayAgo = Date.now() - 24 * 60 * 60 * 1e3;
|
|
73
|
+
const recentPosts = data.trackedPosts.filter(
|
|
74
|
+
(p) => new Date(p.postedAt).getTime() > oneDayAgo
|
|
75
|
+
);
|
|
76
|
+
if (recentPosts.length > 0) {
|
|
77
|
+
const postStats = recentPosts.map((p) => {
|
|
78
|
+
const latest = p.metrics.length > 0 ? p.metrics[p.metrics.length - 1] : null;
|
|
79
|
+
return {
|
|
80
|
+
content: p.content,
|
|
81
|
+
type: p.type,
|
|
82
|
+
likes: latest?.likes ?? 0,
|
|
83
|
+
retweets: latest?.retweets ?? 0,
|
|
84
|
+
replies: latest?.replies ?? 0
|
|
85
|
+
};
|
|
86
|
+
});
|
|
87
|
+
const totalLikes = postStats.reduce((s, p) => s + p.likes, 0);
|
|
88
|
+
const totalRTs = postStats.reduce((s, p) => s + p.retweets, 0);
|
|
89
|
+
const avgLikes = Math.round(totalLikes / postStats.length);
|
|
90
|
+
lines.push(`- Last 24h: ${postStats.length} posts, avg ${avgLikes} likes, ${totalRTs} total retweets`);
|
|
91
|
+
const sorted = [...postStats].sort((a, b) => b.likes - a.likes);
|
|
92
|
+
if (sorted.length > 0 && sorted[0].likes > 0) {
|
|
93
|
+
lines.push(`- Best performing: "${sorted[0].content.slice(0, 60)}..." (${sorted[0].likes} likes, ${sorted[0].retweets} RTs)`);
|
|
94
|
+
}
|
|
95
|
+
if (sorted.length > 1) {
|
|
96
|
+
const worst = sorted[sorted.length - 1];
|
|
97
|
+
lines.push(`- Lowest performing: "${worst.content.slice(0, 60)}..." (${worst.likes} likes)`);
|
|
98
|
+
}
|
|
99
|
+
} else {
|
|
100
|
+
lines.push("- No tracked posts in the last 24 hours yet.");
|
|
101
|
+
}
|
|
102
|
+
if (data.selfMetrics.length > 0) {
|
|
103
|
+
const latest = data.selfMetrics[data.selfMetrics.length - 1];
|
|
104
|
+
lines.push(`- Followers: ${latest.followers} | Following: ${latest.following} | Total tweets: ${latest.totalTweets}`);
|
|
105
|
+
const dayAgoMetric = data.selfMetrics.find(
|
|
106
|
+
(m) => Math.abs(new Date(m.checkedAt).getTime() - (Date.now() - 24 * 60 * 60 * 1e3)) < 12 * 60 * 60 * 1e3
|
|
107
|
+
);
|
|
108
|
+
if (dayAgoMetric) {
|
|
109
|
+
const diff = latest.followers - dayAgoMetric.followers;
|
|
110
|
+
if (diff !== 0) {
|
|
111
|
+
lines.push(`- Follower trend: ${diff > 0 ? "+" : ""}${diff} in the last ~24h`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return lines.length > 0 ? lines.join("\n") : "";
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// src/x-client/rate-limiter.ts
|
|
119
|
+
var RateLimiter = class {
|
|
120
|
+
checkResetDate() {
|
|
121
|
+
const config = loadConfig();
|
|
122
|
+
const now = /* @__PURE__ */ new Date();
|
|
123
|
+
const resetDate = new Date(config.credits.resetDate);
|
|
124
|
+
if (now >= resetDate) {
|
|
125
|
+
config.credits.postsUsedThisMonth = 0;
|
|
126
|
+
const nextReset = new Date(now.getFullYear(), now.getMonth() + 1, 1);
|
|
127
|
+
config.credits.resetDate = nextReset.toISOString();
|
|
128
|
+
saveConfig(config);
|
|
129
|
+
logger.info("Monthly credits reset");
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
canPost() {
|
|
133
|
+
this.checkResetDate();
|
|
134
|
+
const config = loadConfig();
|
|
135
|
+
return config.credits.postsUsedThisMonth < config.credits.monthlyPostLimit;
|
|
136
|
+
}
|
|
137
|
+
remaining() {
|
|
138
|
+
this.checkResetDate();
|
|
139
|
+
const config = loadConfig();
|
|
140
|
+
return config.credits.monthlyPostLimit - config.credits.postsUsedThisMonth;
|
|
141
|
+
}
|
|
142
|
+
consume(count = 1) {
|
|
143
|
+
this.checkResetDate();
|
|
144
|
+
const config = loadConfig();
|
|
145
|
+
config.credits.postsUsedThisMonth += count;
|
|
146
|
+
saveConfig(config);
|
|
147
|
+
const remaining = config.credits.monthlyPostLimit - config.credits.postsUsedThisMonth;
|
|
148
|
+
if (remaining <= Math.floor(config.credits.monthlyPostLimit * 0.2)) {
|
|
149
|
+
logger.warn(`Low credits: ${remaining} posts remaining this month`);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
requireBasicTier(action) {
|
|
153
|
+
const config = loadConfig();
|
|
154
|
+
if (config.xMethod === "api" && config.xApiTier !== "basic") {
|
|
155
|
+
throw new Error(
|
|
156
|
+
`${action} requires X API Basic tier ($200/mo). Current tier: ${config.xApiTier ?? "free"}. Upgrade your API tier or adjust runtime behavior.`
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
var rateLimiter = new RateLimiter();
|
|
162
|
+
|
|
163
|
+
export {
|
|
164
|
+
trackPost,
|
|
165
|
+
getActiveTrackedPosts,
|
|
166
|
+
updatePostMetrics,
|
|
167
|
+
retireOldPosts,
|
|
168
|
+
getPerformanceSummary,
|
|
169
|
+
rateLimiter
|
|
170
|
+
};
|
|
171
|
+
//# sourceMappingURL=chunk-CP6JWCLY.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/memory/performance.ts","../src/x-client/rate-limiter.ts"],"sourcesContent":["import { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { paths } from \"../utils/paths.js\";\n\nexport interface EngagementMetric {\n checkedAt: string;\n likes: number;\n retweets: number;\n replies: number;\n}\n\nexport interface TrackedPost {\n tweetId: string;\n content: string;\n type: \"post\" | \"reply\";\n postedAt: string;\n metrics: EngagementMetric[];\n retired: boolean;\n}\n\nexport interface SelfMetric {\n checkedAt: string;\n followers: number;\n following: number;\n totalTweets: number;\n}\n\nexport interface PerformanceData {\n trackedPosts: TrackedPost[];\n selfMetrics: SelfMetric[];\n}\n\nfunction loadPerformance(): PerformanceData {\n if (!existsSync(paths.performance)) {\n return { trackedPosts: [], selfMetrics: [] };\n }\n try {\n return JSON.parse(readFileSync(paths.performance, \"utf-8\"));\n } catch {\n return { trackedPosts: [], selfMetrics: [] };\n }\n}\n\nfunction savePerformance(data: PerformanceData): void {\n writeFileSync(paths.performance, JSON.stringify(data, null, 2));\n}\n\nexport function trackPost(tweetId: string, content: string, type: \"post\" | \"reply\"): void {\n const data = loadPerformance();\n // Don't double-track\n if (data.trackedPosts.some(p => p.tweetId === tweetId)) return;\n data.trackedPosts.push({\n tweetId,\n content,\n type,\n postedAt: new Date().toISOString(),\n metrics: [],\n retired: false,\n });\n savePerformance(data);\n}\n\nexport function getActiveTrackedPosts(): TrackedPost[] {\n const data = loadPerformance();\n return data.trackedPosts.filter(p => !p.retired);\n}\n\nexport function updatePostMetrics(tweetId: string, metric: EngagementMetric): void {\n const data = loadPerformance();\n const post = data.trackedPosts.find(p => p.tweetId === tweetId);\n if (!post) return;\n post.metrics.push(metric);\n savePerformance(data);\n}\n\nexport function retireOldPosts(): void {\n const data = loadPerformance();\n const cutoff = Date.now() - 72 * 60 * 60 * 1000; // 72 hours\n let changed = false;\n for (const post of data.trackedPosts) {\n if (!post.retired && new Date(post.postedAt).getTime() < cutoff) {\n post.retired = true;\n changed = true;\n }\n }\n // Also prune very old retired posts (older than 30 days) to prevent file bloat\n const pruneCutoff = Date.now() - 30 * 24 * 60 * 60 * 1000;\n const before = data.trackedPosts.length;\n data.trackedPosts = data.trackedPosts.filter(\n p => !p.retired || new Date(p.postedAt).getTime() > pruneCutoff\n );\n if (data.trackedPosts.length !== before) changed = true;\n if (changed) savePerformance(data);\n}\n\nexport function updateSelfMetrics(metric: SelfMetric): void {\n const data = loadPerformance();\n data.selfMetrics.push(metric);\n // Keep only last 100 snapshots\n if (data.selfMetrics.length > 100) {\n data.selfMetrics = data.selfMetrics.slice(-100);\n }\n savePerformance(data);\n}\n\nexport function getPerformanceSummary(): string {\n const data = loadPerformance();\n const lines: string[] = [];\n\n // Post performance (last 24h)\n const oneDayAgo = Date.now() - 24 * 60 * 60 * 1000;\n const recentPosts = data.trackedPosts.filter(\n p => new Date(p.postedAt).getTime() > oneDayAgo\n );\n\n if (recentPosts.length > 0) {\n // Get latest metrics for each post\n const postStats = recentPosts.map(p => {\n const latest = p.metrics.length > 0 ? p.metrics[p.metrics.length - 1] : null;\n return {\n content: p.content,\n type: p.type,\n likes: latest?.likes ?? 0,\n retweets: latest?.retweets ?? 0,\n replies: latest?.replies ?? 0,\n };\n });\n\n const totalLikes = postStats.reduce((s, p) => s + p.likes, 0);\n const totalRTs = postStats.reduce((s, p) => s + p.retweets, 0);\n const avgLikes = Math.round(totalLikes / postStats.length);\n\n lines.push(`- Last 24h: ${postStats.length} posts, avg ${avgLikes} likes, ${totalRTs} total retweets`);\n\n // Best and worst performing\n const sorted = [...postStats].sort((a, b) => b.likes - a.likes);\n if (sorted.length > 0 && sorted[0].likes > 0) {\n lines.push(`- Best performing: \"${sorted[0].content.slice(0, 60)}...\" (${sorted[0].likes} likes, ${sorted[0].retweets} RTs)`);\n }\n if (sorted.length > 1) {\n const worst = sorted[sorted.length - 1];\n lines.push(`- Lowest performing: \"${worst.content.slice(0, 60)}...\" (${worst.likes} likes)`);\n }\n } else {\n lines.push(\"- No tracked posts in the last 24 hours yet.\");\n }\n\n // Self metrics\n if (data.selfMetrics.length > 0) {\n const latest = data.selfMetrics[data.selfMetrics.length - 1];\n lines.push(`- Followers: ${latest.followers} | Following: ${latest.following} | Total tweets: ${latest.totalTweets}`);\n\n // Trend: compare to 24h ago\n const dayAgoMetric = data.selfMetrics.find(m =>\n Math.abs(new Date(m.checkedAt).getTime() - (Date.now() - 24 * 60 * 60 * 1000)) < 12 * 60 * 60 * 1000\n );\n if (dayAgoMetric) {\n const diff = latest.followers - dayAgoMetric.followers;\n if (diff !== 0) {\n lines.push(`- Follower trend: ${diff > 0 ? \"+\" : \"\"}${diff} in the last ~24h`);\n }\n }\n }\n\n return lines.length > 0 ? lines.join(\"\\n\") : \"\";\n}\n","import { loadConfig, saveConfig } from \"../utils/config.js\";\nimport { logger } from \"../utils/logger.js\";\n\nexport class RateLimiter {\n private checkResetDate(): void {\n const config = loadConfig();\n const now = new Date();\n const resetDate = new Date(config.credits.resetDate);\n\n if (now >= resetDate) {\n config.credits.postsUsedThisMonth = 0;\n const nextReset = new Date(now.getFullYear(), now.getMonth() + 1, 1);\n config.credits.resetDate = nextReset.toISOString();\n saveConfig(config);\n logger.info(\"Monthly credits reset\");\n }\n }\n\n canPost(): boolean {\n this.checkResetDate();\n const config = loadConfig();\n return config.credits.postsUsedThisMonth < config.credits.monthlyPostLimit;\n }\n\n remaining(): number {\n this.checkResetDate();\n const config = loadConfig();\n return config.credits.monthlyPostLimit - config.credits.postsUsedThisMonth;\n }\n\n consume(count: number = 1): void {\n this.checkResetDate();\n const config = loadConfig();\n config.credits.postsUsedThisMonth += count;\n saveConfig(config);\n\n const remaining = config.credits.monthlyPostLimit - config.credits.postsUsedThisMonth;\n if (remaining <= Math.floor(config.credits.monthlyPostLimit * 0.2)) {\n logger.warn(`Low credits: ${remaining} posts remaining this month`);\n }\n }\n\n requireBasicTier(action: string): void {\n const config = loadConfig();\n if (config.xMethod === \"api\" && config.xApiTier !== \"basic\") {\n throw new Error(\n `${action} requires X API Basic tier ($200/mo). ` +\n `Current tier: ${config.xApiTier ?? \"free\"}. ` +\n `Upgrade your API tier or adjust runtime behavior.`\n );\n }\n }\n}\n\nexport const rateLimiter = new RateLimiter();\n"],"mappings":"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","names":[]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ensureDirectories,
|
|
3
3
|
paths
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-ZWKTKWS6.js";
|
|
5
5
|
|
|
6
6
|
// src/colony/memory.ts
|
|
7
7
|
import { readFileSync, writeFileSync, existsSync } from "fs";
|
|
@@ -153,4 +153,4 @@ export {
|
|
|
153
153
|
getTodayEntries,
|
|
154
154
|
renderColonyBriefing
|
|
155
155
|
};
|
|
156
|
-
//# sourceMappingURL=chunk-
|
|
156
|
+
//# sourceMappingURL=chunk-D47OFTEK.js.map
|