spora 0.6.3 → 0.7.1
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/README.md +7 -5
- package/dist/autonomy-DAV7X6QS.js +19 -0
- package/dist/{chunk-53YLFYJF.js → chunk-3RYCUGXE.js} +6 -2
- package/dist/chunk-3RYCUGXE.js.map +1 -0
- package/dist/{chunk-LKCYTFWN.js → chunk-AOQ3WLZV.js} +86 -106
- package/dist/chunk-AOQ3WLZV.js.map +1 -0
- package/dist/chunk-E5NR6HT4.js +29 -0
- package/dist/chunk-E5NR6HT4.js.map +1 -0
- package/dist/{chunk-EBO4F5NU.js → chunk-JBYZ7K56.js} +2 -2
- package/dist/chunk-KWWAIS3C.js +180 -0
- package/dist/chunk-KWWAIS3C.js.map +1 -0
- package/dist/{chunk-UINSD4FT.js → chunk-LXQNVVIY.js} +6 -6
- package/dist/{chunk-UINSD4FT.js.map → chunk-LXQNVVIY.js.map} +1 -1
- package/dist/{chunk-AIEXQCQS.js → chunk-M6YOQVSI.js} +2 -2
- package/dist/{chunk-B6RPMDML.js → chunk-NO3NQN67.js} +16 -6
- package/dist/chunk-NO3NQN67.js.map +1 -0
- package/dist/{chunk-QOKQ5OTU.js → chunk-NPV3OV2K.js} +3 -14
- package/dist/chunk-NPV3OV2K.js.map +1 -0
- package/dist/{chunk-4POAJONO.js → chunk-OACD3HGE.js} +7 -7
- package/dist/{chunk-UM57WU5I.js → chunk-P6KZIJYL.js} +2 -2
- package/dist/{chunk-AHXZIGQE.js → chunk-T7L2L7ZL.js} +2 -2
- package/dist/{chunk-ZJZKH7N7.js → chunk-VZBHRUZS.js} +2 -2
- package/dist/chunk-VZBHRUZS.js.map +1 -0
- package/dist/chunk-WIK74GGJ.js +295 -0
- package/dist/chunk-WIK74GGJ.js.map +1 -0
- package/dist/{chunk-YLJVFCT4.js → chunk-WN35MRMF.js} +2 -2
- package/dist/cli.js +168 -137
- package/dist/cli.js.map +1 -1
- package/dist/client-57BQKVYF.js +337 -0
- package/dist/client-57BQKVYF.js.map +1 -0
- package/dist/{colony-STNSQDYA.js → colony-JPZC3R34.js} +7 -7
- package/dist/{config-TFAFYSIW.js → config-FL4VJVKZ.js} +3 -3
- package/dist/{crypto-FHSQ72NU.js → crypto-NOXNL4GP.js} +3 -3
- package/dist/{goals-5TAPXNR2.js → goals-RBKLMILE.js} +3 -3
- package/dist/{heartbeat-5PWQERHL.js → heartbeat-TNEPE3ZP.js} +83 -92
- package/dist/heartbeat-TNEPE3ZP.js.map +1 -0
- package/dist/{identity-O4FLSZKZ.js → identity-VDUW4I2K.js} +3 -3
- package/dist/{init-E54LQDKA.js → init-ISSXETHY.js} +59 -46
- package/dist/init-ISSXETHY.js.map +1 -0
- package/dist/llm-T33QTPVW.js +22 -0
- package/dist/mcp-server.js +28 -28
- package/dist/mcp-server.js.map +1 -1
- package/dist/{memory-O3AJIKBX.js → memory-OIAH33G2.js} +3 -3
- package/dist/{memory-7FBE26K3.js → memory-PNW7SX7A.js} +3 -3
- package/dist/{paths-5GFUUHCZ.js → paths-BYR6MEPR.js} +2 -2
- package/dist/prompt-builder-5NYONN2W.js +23 -0
- package/dist/queue-G5PTE6R6.js +14 -0
- package/dist/{strategy-S45TX766.js → strategy-Z4JSFHSP.js} +3 -3
- package/dist/{web-chat-P6PZ3TP6.js → web-chat-3HM35XM4.js} +30 -85
- package/dist/web-chat-3HM35XM4.js.map +1 -0
- package/dist/x-client-GY6XSPK6.js +12 -0
- package/package.json +1 -1
- package/dist/account-creator-ZD643X3Z.js +0 -498
- package/dist/account-creator-ZD643X3Z.js.map +0 -1
- package/dist/chunk-53YLFYJF.js.map +0 -1
- package/dist/chunk-55XPDJ6P.js +0 -124
- package/dist/chunk-55XPDJ6P.js.map +0 -1
- package/dist/chunk-B6RPMDML.js.map +0 -1
- package/dist/chunk-H2N5G6R7.js +0 -249
- package/dist/chunk-H2N5G6R7.js.map +0 -1
- package/dist/chunk-LKCYTFWN.js.map +0 -1
- package/dist/chunk-QOKQ5OTU.js.map +0 -1
- package/dist/chunk-ZJZKH7N7.js.map +0 -1
- package/dist/chunk-ZMTC7BYD.js +0 -32
- package/dist/chunk-ZMTC7BYD.js.map +0 -1
- package/dist/client-GCHDQ6W2.js +0 -350
- package/dist/client-GCHDQ6W2.js.map +0 -1
- package/dist/client-I7Q4HC4F.js +0 -401
- package/dist/client-I7Q4HC4F.js.map +0 -1
- package/dist/decision-engine-SO33N7CT.js +0 -19
- package/dist/heartbeat-5PWQERHL.js.map +0 -1
- package/dist/init-E54LQDKA.js.map +0 -1
- package/dist/llm-3LSNADSR.js +0 -16
- package/dist/prompt-builder-3LQFX6QK.js +0 -23
- package/dist/queue-CXMLAQ6X.js +0 -14
- package/dist/web-chat-P6PZ3TP6.js.map +0 -1
- package/dist/x-client-7LMNSOTE.js +0 -12
- /package/dist/{config-TFAFYSIW.js.map → autonomy-DAV7X6QS.js.map} +0 -0
- /package/dist/{chunk-EBO4F5NU.js.map → chunk-JBYZ7K56.js.map} +0 -0
- /package/dist/{chunk-AIEXQCQS.js.map → chunk-M6YOQVSI.js.map} +0 -0
- /package/dist/{chunk-4POAJONO.js.map → chunk-OACD3HGE.js.map} +0 -0
- /package/dist/{chunk-UM57WU5I.js.map → chunk-P6KZIJYL.js.map} +0 -0
- /package/dist/{chunk-AHXZIGQE.js.map → chunk-T7L2L7ZL.js.map} +0 -0
- /package/dist/{chunk-YLJVFCT4.js.map → chunk-WN35MRMF.js.map} +0 -0
- /package/dist/{colony-STNSQDYA.js.map → colony-JPZC3R34.js.map} +0 -0
- /package/dist/{crypto-FHSQ72NU.js.map → config-FL4VJVKZ.js.map} +0 -0
- /package/dist/{decision-engine-SO33N7CT.js.map → crypto-NOXNL4GP.js.map} +0 -0
- /package/dist/{goals-5TAPXNR2.js.map → goals-RBKLMILE.js.map} +0 -0
- /package/dist/{identity-O4FLSZKZ.js.map → identity-VDUW4I2K.js.map} +0 -0
- /package/dist/{llm-3LSNADSR.js.map → llm-T33QTPVW.js.map} +0 -0
- /package/dist/{memory-7FBE26K3.js.map → memory-OIAH33G2.js.map} +0 -0
- /package/dist/{memory-O3AJIKBX.js.map → memory-PNW7SX7A.js.map} +0 -0
- /package/dist/{paths-5GFUUHCZ.js.map → paths-BYR6MEPR.js.map} +0 -0
- /package/dist/{prompt-builder-3LQFX6QK.js.map → prompt-builder-5NYONN2W.js.map} +0 -0
- /package/dist/{queue-CXMLAQ6X.js.map → queue-G5PTE6R6.js.map} +0 -0
- /package/dist/{strategy-S45TX766.js.map → strategy-Z4JSFHSP.js.map} +0 -0
- /package/dist/{x-client-7LMNSOTE.js.map → x-client-GY6XSPK6.js.map} +0 -0
package/dist/client-I7Q4HC4F.js
DELETED
|
@@ -1,401 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
rateLimiter
|
|
3
|
-
} from "./chunk-UINSD4FT.js";
|
|
4
|
-
import "./chunk-B6RPMDML.js";
|
|
5
|
-
import {
|
|
6
|
-
identityExists,
|
|
7
|
-
loadIdentity
|
|
8
|
-
} from "./chunk-AIEXQCQS.js";
|
|
9
|
-
import {
|
|
10
|
-
loadCredentials
|
|
11
|
-
} from "./chunk-ZJZKH7N7.js";
|
|
12
|
-
import {
|
|
13
|
-
logger
|
|
14
|
-
} from "./chunk-QOKQ5OTU.js";
|
|
15
|
-
import {
|
|
16
|
-
logInteraction
|
|
17
|
-
} from "./chunk-EBO4F5NU.js";
|
|
18
|
-
import {
|
|
19
|
-
ensureDirectories,
|
|
20
|
-
paths
|
|
21
|
-
} from "./chunk-53YLFYJF.js";
|
|
22
|
-
|
|
23
|
-
// src/x-client/browser/client.ts
|
|
24
|
-
import { chromium } from "playwright";
|
|
25
|
-
import { existsSync, readFileSync, writeFileSync } from "fs";
|
|
26
|
-
var X_BASE = "https://x.com";
|
|
27
|
-
var XBrowserClient = class {
|
|
28
|
-
browser = null;
|
|
29
|
-
context = null;
|
|
30
|
-
page = null;
|
|
31
|
-
async ensureBrowser() {
|
|
32
|
-
if (this.page && !this.page.isClosed()) return this.page;
|
|
33
|
-
this.browser = await chromium.launch({ headless: true });
|
|
34
|
-
if (existsSync(paths.browserAuth)) {
|
|
35
|
-
const storageState = JSON.parse(readFileSync(paths.browserAuth, "utf-8"));
|
|
36
|
-
this.context = await this.browser.newContext({ storageState });
|
|
37
|
-
} else {
|
|
38
|
-
this.context = await this.browser.newContext();
|
|
39
|
-
}
|
|
40
|
-
this.page = await this.context.newPage();
|
|
41
|
-
await this.page.goto(X_BASE, { waitUntil: "domcontentloaded" });
|
|
42
|
-
const isLoggedIn = await this.page.locator('[data-testid="SideNav_AccountSwitcher_Button"]').isVisible({ timeout: 5e3 }).catch(() => false);
|
|
43
|
-
if (!isLoggedIn) {
|
|
44
|
-
await this.login();
|
|
45
|
-
}
|
|
46
|
-
return this.page;
|
|
47
|
-
}
|
|
48
|
-
async login() {
|
|
49
|
-
const creds = loadCredentials();
|
|
50
|
-
if (!creds.username || !creds.password) {
|
|
51
|
-
throw new Error("Browser mode requires username and password credentials");
|
|
52
|
-
}
|
|
53
|
-
const page = this.page;
|
|
54
|
-
await page.goto(`${X_BASE}/login`, { waitUntil: "domcontentloaded" });
|
|
55
|
-
await page.waitForTimeout(2e3);
|
|
56
|
-
const usernameInput = page.locator('input[autocomplete="username"]');
|
|
57
|
-
await usernameInput.waitFor({ timeout: 1e4 });
|
|
58
|
-
await usernameInput.fill(creds.username);
|
|
59
|
-
await page.locator("text=Next").click();
|
|
60
|
-
await page.waitForTimeout(2e3);
|
|
61
|
-
const emailInput = page.locator('input[data-testid="ocfEnterTextTextInput"]');
|
|
62
|
-
const emailVisible = await emailInput.isVisible({ timeout: 3e3 }).catch(() => false);
|
|
63
|
-
if (emailVisible && creds.email) {
|
|
64
|
-
await emailInput.fill(creds.email);
|
|
65
|
-
await page.locator("text=Next").click();
|
|
66
|
-
await page.waitForTimeout(2e3);
|
|
67
|
-
}
|
|
68
|
-
const passwordInput = page.locator('input[type="password"]');
|
|
69
|
-
await passwordInput.waitFor({ timeout: 1e4 });
|
|
70
|
-
await passwordInput.fill(creds.password);
|
|
71
|
-
await page.locator('[data-testid="LoginForm_Login_Button"]').click();
|
|
72
|
-
await page.waitForTimeout(3e3);
|
|
73
|
-
await this.saveSession();
|
|
74
|
-
logger.info("Logged into X via browser");
|
|
75
|
-
}
|
|
76
|
-
async saveSession() {
|
|
77
|
-
if (!this.context) return;
|
|
78
|
-
ensureDirectories();
|
|
79
|
-
const state = await this.context.storageState();
|
|
80
|
-
writeFileSync(paths.browserAuth, JSON.stringify(state));
|
|
81
|
-
}
|
|
82
|
-
getHandle() {
|
|
83
|
-
if (identityExists()) {
|
|
84
|
-
return loadIdentity().handle;
|
|
85
|
-
}
|
|
86
|
-
const creds = loadCredentials();
|
|
87
|
-
if (creds.username) return creds.username;
|
|
88
|
-
throw new Error("No handle found. Create a Spore identity first.");
|
|
89
|
-
}
|
|
90
|
-
async waitForNavigation(page, timeout = 5e3) {
|
|
91
|
-
await page.waitForTimeout(timeout);
|
|
92
|
-
}
|
|
93
|
-
async postTweet(content) {
|
|
94
|
-
if (!rateLimiter.canPost()) {
|
|
95
|
-
return { success: false, error: "Monthly post limit reached" };
|
|
96
|
-
}
|
|
97
|
-
try {
|
|
98
|
-
const page = await this.ensureBrowser();
|
|
99
|
-
await page.goto(X_BASE, { waitUntil: "domcontentloaded" });
|
|
100
|
-
await page.waitForTimeout(2e3);
|
|
101
|
-
const composeButton = page.locator('[data-testid="tweetButtonInline"]').first();
|
|
102
|
-
const composeArea = page.locator('[data-testid="tweetTextarea_0"]').first();
|
|
103
|
-
const areaVisible = await composeArea.isVisible({ timeout: 3e3 }).catch(() => false);
|
|
104
|
-
if (!areaVisible) {
|
|
105
|
-
await page.locator('[data-testid="SideNav_NewTweet_Button"]').click();
|
|
106
|
-
await page.waitForTimeout(1e3);
|
|
107
|
-
}
|
|
108
|
-
const textarea = page.locator('[data-testid="tweetTextarea_0"]').first();
|
|
109
|
-
await textarea.waitFor({ timeout: 5e3 });
|
|
110
|
-
await textarea.fill(content);
|
|
111
|
-
await page.waitForTimeout(500);
|
|
112
|
-
await page.locator('[data-testid="tweetButton"]').click();
|
|
113
|
-
await page.waitForTimeout(3e3);
|
|
114
|
-
rateLimiter.consume();
|
|
115
|
-
logInteraction({
|
|
116
|
-
id: `int-${Date.now()}`,
|
|
117
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
118
|
-
type: "post",
|
|
119
|
-
content,
|
|
120
|
-
creditsUsed: 1,
|
|
121
|
-
success: true
|
|
122
|
-
});
|
|
123
|
-
await this.saveSession();
|
|
124
|
-
return { success: true };
|
|
125
|
-
} catch (error) {
|
|
126
|
-
logger.error("Failed to post tweet via browser", error);
|
|
127
|
-
return { success: false, error: error.message };
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
async replyToTweet(tweetId, content) {
|
|
131
|
-
if (!rateLimiter.canPost()) {
|
|
132
|
-
return { success: false, error: "Monthly post limit reached" };
|
|
133
|
-
}
|
|
134
|
-
try {
|
|
135
|
-
const page = await this.ensureBrowser();
|
|
136
|
-
const handle = this.getHandle();
|
|
137
|
-
await page.goto(`${X_BASE}/${handle}/status/${tweetId}`, {
|
|
138
|
-
waitUntil: "domcontentloaded"
|
|
139
|
-
});
|
|
140
|
-
await page.waitForTimeout(2e3);
|
|
141
|
-
const replyArea = page.locator('[data-testid="tweetTextarea_0"]').first();
|
|
142
|
-
await replyArea.waitFor({ timeout: 5e3 });
|
|
143
|
-
await replyArea.fill(content);
|
|
144
|
-
await page.waitForTimeout(500);
|
|
145
|
-
await page.locator('[data-testid="tweetButton"]').click();
|
|
146
|
-
await page.waitForTimeout(3e3);
|
|
147
|
-
rateLimiter.consume();
|
|
148
|
-
logInteraction({
|
|
149
|
-
id: `int-${Date.now()}`,
|
|
150
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
151
|
-
type: "reply",
|
|
152
|
-
inReplyTo: tweetId,
|
|
153
|
-
content,
|
|
154
|
-
creditsUsed: 1,
|
|
155
|
-
success: true
|
|
156
|
-
});
|
|
157
|
-
await this.saveSession();
|
|
158
|
-
return { success: true };
|
|
159
|
-
} catch (error) {
|
|
160
|
-
logger.error("Failed to reply via browser", error);
|
|
161
|
-
return { success: false, error: error.message };
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
async deleteTweet(tweetId) {
|
|
165
|
-
try {
|
|
166
|
-
const page = await this.ensureBrowser();
|
|
167
|
-
const handle = this.getHandle();
|
|
168
|
-
await page.goto(`${X_BASE}/${handle}/status/${tweetId}`, {
|
|
169
|
-
waitUntil: "domcontentloaded"
|
|
170
|
-
});
|
|
171
|
-
await page.waitForTimeout(2e3);
|
|
172
|
-
await page.locator('[data-testid="caret"]').first().click();
|
|
173
|
-
await page.waitForTimeout(1e3);
|
|
174
|
-
await page.locator("text=Delete").click();
|
|
175
|
-
await page.waitForTimeout(1e3);
|
|
176
|
-
await page.locator('[data-testid="confirmationSheetConfirm"]').click();
|
|
177
|
-
await page.waitForTimeout(2e3);
|
|
178
|
-
await this.saveSession();
|
|
179
|
-
return { success: true, tweetId };
|
|
180
|
-
} catch (error) {
|
|
181
|
-
return { success: false, error: error.message };
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
async likeTweet(tweetId) {
|
|
185
|
-
try {
|
|
186
|
-
const page = await this.ensureBrowser();
|
|
187
|
-
await page.goto(`${X_BASE}/i/status/${tweetId}`, {
|
|
188
|
-
waitUntil: "domcontentloaded"
|
|
189
|
-
});
|
|
190
|
-
await page.waitForTimeout(2e3);
|
|
191
|
-
await page.locator('[data-testid="like"]').first().click();
|
|
192
|
-
await page.waitForTimeout(1e3);
|
|
193
|
-
logInteraction({
|
|
194
|
-
id: `int-${Date.now()}`,
|
|
195
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
196
|
-
type: "like",
|
|
197
|
-
tweetId,
|
|
198
|
-
creditsUsed: 0,
|
|
199
|
-
success: true
|
|
200
|
-
});
|
|
201
|
-
await this.saveSession();
|
|
202
|
-
return { success: true, tweetId };
|
|
203
|
-
} catch (error) {
|
|
204
|
-
return { success: false, error: error.message };
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
async unlikeTweet(tweetId) {
|
|
208
|
-
try {
|
|
209
|
-
const page = await this.ensureBrowser();
|
|
210
|
-
await page.goto(`${X_BASE}/i/status/${tweetId}`, {
|
|
211
|
-
waitUntil: "domcontentloaded"
|
|
212
|
-
});
|
|
213
|
-
await page.waitForTimeout(2e3);
|
|
214
|
-
await page.locator('[data-testid="unlike"]').first().click();
|
|
215
|
-
await page.waitForTimeout(1e3);
|
|
216
|
-
await this.saveSession();
|
|
217
|
-
return { success: true, tweetId };
|
|
218
|
-
} catch (error) {
|
|
219
|
-
return { success: false, error: error.message };
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
async retweet(tweetId) {
|
|
223
|
-
try {
|
|
224
|
-
const page = await this.ensureBrowser();
|
|
225
|
-
await page.goto(`${X_BASE}/i/status/${tweetId}`, {
|
|
226
|
-
waitUntil: "domcontentloaded"
|
|
227
|
-
});
|
|
228
|
-
await page.waitForTimeout(2e3);
|
|
229
|
-
await page.locator('[data-testid="retweet"]').first().click();
|
|
230
|
-
await page.waitForTimeout(1e3);
|
|
231
|
-
await page.locator('[data-testid="retweetConfirm"]').click();
|
|
232
|
-
await page.waitForTimeout(1e3);
|
|
233
|
-
logInteraction({
|
|
234
|
-
id: `int-${Date.now()}`,
|
|
235
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
236
|
-
type: "retweet",
|
|
237
|
-
tweetId,
|
|
238
|
-
creditsUsed: 0,
|
|
239
|
-
success: true
|
|
240
|
-
});
|
|
241
|
-
await this.saveSession();
|
|
242
|
-
return { success: true, tweetId };
|
|
243
|
-
} catch (error) {
|
|
244
|
-
return { success: false, error: error.message };
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
async unretweet(tweetId) {
|
|
248
|
-
try {
|
|
249
|
-
const page = await this.ensureBrowser();
|
|
250
|
-
await page.goto(`${X_BASE}/i/status/${tweetId}`, {
|
|
251
|
-
waitUntil: "domcontentloaded"
|
|
252
|
-
});
|
|
253
|
-
await page.waitForTimeout(2e3);
|
|
254
|
-
await page.locator('[data-testid="unretweet"]').first().click();
|
|
255
|
-
await page.waitForTimeout(1e3);
|
|
256
|
-
await page.locator('[data-testid="unretweetConfirm"]').click();
|
|
257
|
-
await page.waitForTimeout(1e3);
|
|
258
|
-
await this.saveSession();
|
|
259
|
-
return { success: true, tweetId };
|
|
260
|
-
} catch (error) {
|
|
261
|
-
return { success: false, error: error.message };
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
async followUser(userId) {
|
|
265
|
-
try {
|
|
266
|
-
const page = await this.ensureBrowser();
|
|
267
|
-
await page.goto(`${X_BASE}/${userId}`, { waitUntil: "domcontentloaded" });
|
|
268
|
-
await page.waitForTimeout(2e3);
|
|
269
|
-
const followButton = page.locator('[data-testid$="-follow"]').first();
|
|
270
|
-
await followButton.click();
|
|
271
|
-
await page.waitForTimeout(1e3);
|
|
272
|
-
logInteraction({
|
|
273
|
-
id: `int-${Date.now()}`,
|
|
274
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
275
|
-
type: "follow",
|
|
276
|
-
targetUserId: userId,
|
|
277
|
-
creditsUsed: 0,
|
|
278
|
-
success: true
|
|
279
|
-
});
|
|
280
|
-
await this.saveSession();
|
|
281
|
-
return { success: true };
|
|
282
|
-
} catch (error) {
|
|
283
|
-
return { success: false, error: error.message };
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
async unfollowUser(userId) {
|
|
287
|
-
try {
|
|
288
|
-
const page = await this.ensureBrowser();
|
|
289
|
-
await page.goto(`${X_BASE}/${userId}`, { waitUntil: "domcontentloaded" });
|
|
290
|
-
await page.waitForTimeout(2e3);
|
|
291
|
-
const unfollowButton = page.locator('[data-testid$="-unfollow"]').first();
|
|
292
|
-
await unfollowButton.click();
|
|
293
|
-
await page.waitForTimeout(1e3);
|
|
294
|
-
await page.locator('[data-testid="confirmationSheetConfirm"]').click();
|
|
295
|
-
await page.waitForTimeout(1e3);
|
|
296
|
-
await this.saveSession();
|
|
297
|
-
return { success: true };
|
|
298
|
-
} catch (error) {
|
|
299
|
-
return { success: false, error: error.message };
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
async getTimeline(options) {
|
|
303
|
-
try {
|
|
304
|
-
const page = await this.ensureBrowser();
|
|
305
|
-
await page.goto(X_BASE, { waitUntil: "domcontentloaded" });
|
|
306
|
-
await page.waitForTimeout(3e3);
|
|
307
|
-
const tweets = await this.scrapeTweets(page, options?.count ?? 20);
|
|
308
|
-
return tweets;
|
|
309
|
-
} catch (error) {
|
|
310
|
-
logger.error("Failed to read timeline via browser", error);
|
|
311
|
-
return [];
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
async getMentions(options) {
|
|
315
|
-
try {
|
|
316
|
-
const page = await this.ensureBrowser();
|
|
317
|
-
await page.goto(`${X_BASE}/notifications/mentions`, {
|
|
318
|
-
waitUntil: "domcontentloaded"
|
|
319
|
-
});
|
|
320
|
-
await page.waitForTimeout(3e3);
|
|
321
|
-
const tweets = await this.scrapeTweets(page, options?.count ?? 20);
|
|
322
|
-
return tweets;
|
|
323
|
-
} catch (error) {
|
|
324
|
-
logger.error("Failed to read mentions via browser", error);
|
|
325
|
-
return [];
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
async searchTweets(query, options) {
|
|
329
|
-
try {
|
|
330
|
-
const page = await this.ensureBrowser();
|
|
331
|
-
const encodedQuery = encodeURIComponent(query);
|
|
332
|
-
await page.goto(`${X_BASE}/search?q=${encodedQuery}&f=live`, {
|
|
333
|
-
waitUntil: "domcontentloaded"
|
|
334
|
-
});
|
|
335
|
-
await page.waitForTimeout(3e3);
|
|
336
|
-
const tweets = await this.scrapeTweets(page, options?.count ?? 20);
|
|
337
|
-
return tweets;
|
|
338
|
-
} catch (error) {
|
|
339
|
-
logger.error("Failed to search via browser", error);
|
|
340
|
-
return [];
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
async getProfile(handle) {
|
|
344
|
-
const page = await this.ensureBrowser();
|
|
345
|
-
await page.goto(`${X_BASE}/${handle}`, { waitUntil: "domcontentloaded" });
|
|
346
|
-
await page.waitForTimeout(3e3);
|
|
347
|
-
const name = await page.locator('[data-testid="UserName"] span').first().textContent() ?? handle;
|
|
348
|
-
const bio = await page.locator('[data-testid="UserDescription"]').textContent().catch(() => "") ?? "";
|
|
349
|
-
const followersText = await page.locator(`a[href="/${handle}/verified_followers"] span`).first().textContent().catch(() => "0") ?? "0";
|
|
350
|
-
const followingText = await page.locator(`a[href="/${handle}/following"] span`).first().textContent().catch(() => "0") ?? "0";
|
|
351
|
-
await this.saveSession();
|
|
352
|
-
return {
|
|
353
|
-
id: handle,
|
|
354
|
-
handle,
|
|
355
|
-
name,
|
|
356
|
-
bio,
|
|
357
|
-
followersCount: parseInt(followersText.replace(/[,K.M]/g, "")) || 0,
|
|
358
|
-
followingCount: parseInt(followingText.replace(/[,K.M]/g, "")) || 0,
|
|
359
|
-
tweetCount: 0,
|
|
360
|
-
verified: false
|
|
361
|
-
};
|
|
362
|
-
}
|
|
363
|
-
async scrapeTweets(page, count) {
|
|
364
|
-
const tweets = [];
|
|
365
|
-
const articles = page.locator('article[data-testid="tweet"]');
|
|
366
|
-
const articleCount = await articles.count();
|
|
367
|
-
for (let i = 0; i < Math.min(articleCount, count); i++) {
|
|
368
|
-
try {
|
|
369
|
-
const article = articles.nth(i);
|
|
370
|
-
const tweetText = await article.locator('[data-testid="tweetText"]').textContent().catch(() => "") ?? "";
|
|
371
|
-
const userLink = article.locator('a[role="link"][href*="/"]').first();
|
|
372
|
-
const href = await userLink.getAttribute("href").catch(() => "") ?? "";
|
|
373
|
-
const authorHandle = href.replace("/", "");
|
|
374
|
-
const time = article.locator("time").first();
|
|
375
|
-
const datetime = await time.getAttribute("datetime").catch(() => "") ?? "";
|
|
376
|
-
tweets.push({
|
|
377
|
-
id: `browser-${Date.now()}-${i}`,
|
|
378
|
-
text: tweetText,
|
|
379
|
-
authorId: authorHandle,
|
|
380
|
-
authorHandle,
|
|
381
|
-
createdAt: datetime
|
|
382
|
-
});
|
|
383
|
-
} catch {
|
|
384
|
-
continue;
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
return tweets;
|
|
388
|
-
}
|
|
389
|
-
async close() {
|
|
390
|
-
if (this.page) await this.page.close().catch(() => {
|
|
391
|
-
});
|
|
392
|
-
if (this.context) await this.context.close().catch(() => {
|
|
393
|
-
});
|
|
394
|
-
if (this.browser) await this.browser.close().catch(() => {
|
|
395
|
-
});
|
|
396
|
-
}
|
|
397
|
-
};
|
|
398
|
-
export {
|
|
399
|
-
XBrowserClient
|
|
400
|
-
};
|
|
401
|
-
//# sourceMappingURL=client-I7Q4HC4F.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/x-client/browser/client.ts"],"sourcesContent":["import { chromium, type Browser, type Page, type BrowserContext } from \"playwright\";\nimport { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { loadCredentials } from \"../../utils/crypto.js\";\nimport { loadIdentity, identityExists } from \"../../identity/index.js\";\nimport { logInteraction } from \"../../memory/index.js\";\nimport { rateLimiter } from \"../rate-limiter.js\";\nimport { paths, ensureDirectories } from \"../../utils/paths.js\";\nimport { logger } from \"../../utils/logger.js\";\nimport type {\n XClientInterface,\n Tweet,\n UserProfile,\n PostResult,\n TimelineOptions,\n SearchOptions,\n} from \"../types.js\";\n\nconst X_BASE = \"https://x.com\";\n\nexport class XBrowserClient implements XClientInterface {\n private browser: Browser | null = null;\n private context: BrowserContext | null = null;\n private page: Page | null = null;\n\n private async ensureBrowser(): Promise<Page> {\n if (this.page && !this.page.isClosed()) return this.page;\n\n this.browser = await chromium.launch({ headless: true });\n\n // Restore session if available\n if (existsSync(paths.browserAuth)) {\n const storageState = JSON.parse(readFileSync(paths.browserAuth, \"utf-8\"));\n this.context = await this.browser.newContext({ storageState });\n } else {\n this.context = await this.browser.newContext();\n }\n\n this.page = await this.context.newPage();\n\n // Check if we're logged in\n await this.page.goto(X_BASE, { waitUntil: \"domcontentloaded\" });\n const isLoggedIn = await this.page\n .locator('[data-testid=\"SideNav_AccountSwitcher_Button\"]')\n .isVisible({ timeout: 5000 })\n .catch(() => false);\n\n if (!isLoggedIn) {\n await this.login();\n }\n\n return this.page;\n }\n\n private async login(): Promise<void> {\n const creds = loadCredentials();\n if (!creds.username || !creds.password) {\n throw new Error(\"Browser mode requires username and password credentials\");\n }\n\n const page = this.page!;\n\n await page.goto(`${X_BASE}/login`, { waitUntil: \"domcontentloaded\" });\n await page.waitForTimeout(2000);\n\n // Enter username\n const usernameInput = page.locator('input[autocomplete=\"username\"]');\n await usernameInput.waitFor({ timeout: 10000 });\n await usernameInput.fill(creds.username);\n await page.locator('text=Next').click();\n await page.waitForTimeout(2000);\n\n // Check for email verification step\n const emailInput = page.locator('input[data-testid=\"ocfEnterTextTextInput\"]');\n const emailVisible = await emailInput.isVisible({ timeout: 3000 }).catch(() => false);\n if (emailVisible && creds.email) {\n await emailInput.fill(creds.email);\n await page.locator('text=Next').click();\n await page.waitForTimeout(2000);\n }\n\n // Enter password\n const passwordInput = page.locator('input[type=\"password\"]');\n await passwordInput.waitFor({ timeout: 10000 });\n await passwordInput.fill(creds.password);\n await page.locator('[data-testid=\"LoginForm_Login_Button\"]').click();\n await page.waitForTimeout(3000);\n\n // Save session\n await this.saveSession();\n logger.info(\"Logged into X via browser\");\n }\n\n private async saveSession(): Promise<void> {\n if (!this.context) return;\n ensureDirectories();\n const state = await this.context.storageState();\n writeFileSync(paths.browserAuth, JSON.stringify(state));\n }\n\n private getHandle(): string {\n if (identityExists()) {\n return loadIdentity().handle;\n }\n const creds = loadCredentials();\n if (creds.username) return creds.username;\n throw new Error(\"No handle found. Create a Spore identity first.\");\n }\n\n private async waitForNavigation(page: Page, timeout = 5000): Promise<void> {\n await page.waitForTimeout(timeout);\n }\n\n async postTweet(content: string): Promise<PostResult> {\n if (!rateLimiter.canPost()) {\n return { success: false, error: \"Monthly post limit reached\" };\n }\n\n try {\n const page = await this.ensureBrowser();\n await page.goto(X_BASE, { waitUntil: \"domcontentloaded\" });\n await page.waitForTimeout(2000);\n\n // Click the tweet compose area\n const composeButton = page.locator('[data-testid=\"tweetButtonInline\"]').first();\n const composeArea = page.locator('[data-testid=\"tweetTextarea_0\"]').first();\n\n // Try clicking the compose area directly\n const areaVisible = await composeArea.isVisible({ timeout: 3000 }).catch(() => false);\n if (!areaVisible) {\n // Click the compose button in sidebar\n await page.locator('[data-testid=\"SideNav_NewTweet_Button\"]').click();\n await page.waitForTimeout(1000);\n }\n\n // Type the tweet\n const textarea = page.locator('[data-testid=\"tweetTextarea_0\"]').first();\n await textarea.waitFor({ timeout: 5000 });\n await textarea.fill(content);\n await page.waitForTimeout(500);\n\n // Click the post button\n await page.locator('[data-testid=\"tweetButton\"]').click();\n await page.waitForTimeout(3000);\n\n rateLimiter.consume();\n logInteraction({\n id: `int-${Date.now()}`,\n timestamp: new Date().toISOString(),\n type: \"post\",\n content,\n creditsUsed: 1,\n success: true,\n });\n\n await this.saveSession();\n return { success: true };\n } catch (error) {\n logger.error(\"Failed to post tweet via browser\", error);\n return { success: false, error: (error as Error).message };\n }\n }\n\n async replyToTweet(tweetId: string, content: string): Promise<PostResult> {\n if (!rateLimiter.canPost()) {\n return { success: false, error: \"Monthly post limit reached\" };\n }\n\n try {\n const page = await this.ensureBrowser();\n const handle = this.getHandle();\n\n // Navigate to the tweet\n await page.goto(`${X_BASE}/${handle}/status/${tweetId}`, {\n waitUntil: \"domcontentloaded\",\n });\n await page.waitForTimeout(2000);\n\n // Click reply area\n const replyArea = page.locator('[data-testid=\"tweetTextarea_0\"]').first();\n await replyArea.waitFor({ timeout: 5000 });\n await replyArea.fill(content);\n await page.waitForTimeout(500);\n\n // Click reply button\n await page.locator('[data-testid=\"tweetButton\"]').click();\n await page.waitForTimeout(3000);\n\n rateLimiter.consume();\n logInteraction({\n id: `int-${Date.now()}`,\n timestamp: new Date().toISOString(),\n type: \"reply\",\n inReplyTo: tweetId,\n content,\n creditsUsed: 1,\n success: true,\n });\n\n await this.saveSession();\n return { success: true };\n } catch (error) {\n logger.error(\"Failed to reply via browser\", error);\n return { success: false, error: (error as Error).message };\n }\n }\n\n async deleteTweet(tweetId: string): Promise<PostResult> {\n try {\n const page = await this.ensureBrowser();\n const handle = this.getHandle();\n\n await page.goto(`${X_BASE}/${handle}/status/${tweetId}`, {\n waitUntil: \"domcontentloaded\",\n });\n await page.waitForTimeout(2000);\n\n // Click the more options menu\n await page.locator('[data-testid=\"caret\"]').first().click();\n await page.waitForTimeout(1000);\n\n // Click delete\n await page.locator('text=Delete').click();\n await page.waitForTimeout(1000);\n\n // Confirm\n await page.locator('[data-testid=\"confirmationSheetConfirm\"]').click();\n await page.waitForTimeout(2000);\n\n await this.saveSession();\n return { success: true, tweetId };\n } catch (error) {\n return { success: false, error: (error as Error).message };\n }\n }\n\n async likeTweet(tweetId: string): Promise<PostResult> {\n try {\n const page = await this.ensureBrowser();\n\n // Navigate to a page that shows the tweet, then like it\n await page.goto(`${X_BASE}/i/status/${tweetId}`, {\n waitUntil: \"domcontentloaded\",\n });\n await page.waitForTimeout(2000);\n\n await page.locator('[data-testid=\"like\"]').first().click();\n await page.waitForTimeout(1000);\n\n logInteraction({\n id: `int-${Date.now()}`,\n timestamp: new Date().toISOString(),\n type: \"like\",\n tweetId,\n creditsUsed: 0,\n success: true,\n });\n\n await this.saveSession();\n return { success: true, tweetId };\n } catch (error) {\n return { success: false, error: (error as Error).message };\n }\n }\n\n async unlikeTweet(tweetId: string): Promise<PostResult> {\n try {\n const page = await this.ensureBrowser();\n await page.goto(`${X_BASE}/i/status/${tweetId}`, {\n waitUntil: \"domcontentloaded\",\n });\n await page.waitForTimeout(2000);\n\n await page.locator('[data-testid=\"unlike\"]').first().click();\n await page.waitForTimeout(1000);\n\n await this.saveSession();\n return { success: true, tweetId };\n } catch (error) {\n return { success: false, error: (error as Error).message };\n }\n }\n\n async retweet(tweetId: string): Promise<PostResult> {\n try {\n const page = await this.ensureBrowser();\n await page.goto(`${X_BASE}/i/status/${tweetId}`, {\n waitUntil: \"domcontentloaded\",\n });\n await page.waitForTimeout(2000);\n\n await page.locator('[data-testid=\"retweet\"]').first().click();\n await page.waitForTimeout(1000);\n await page.locator('[data-testid=\"retweetConfirm\"]').click();\n await page.waitForTimeout(1000);\n\n logInteraction({\n id: `int-${Date.now()}`,\n timestamp: new Date().toISOString(),\n type: \"retweet\",\n tweetId,\n creditsUsed: 0,\n success: true,\n });\n\n await this.saveSession();\n return { success: true, tweetId };\n } catch (error) {\n return { success: false, error: (error as Error).message };\n }\n }\n\n async unretweet(tweetId: string): Promise<PostResult> {\n try {\n const page = await this.ensureBrowser();\n await page.goto(`${X_BASE}/i/status/${tweetId}`, {\n waitUntil: \"domcontentloaded\",\n });\n await page.waitForTimeout(2000);\n\n await page.locator('[data-testid=\"unretweet\"]').first().click();\n await page.waitForTimeout(1000);\n await page.locator('[data-testid=\"unretweetConfirm\"]').click();\n await page.waitForTimeout(1000);\n\n await this.saveSession();\n return { success: true, tweetId };\n } catch (error) {\n return { success: false, error: (error as Error).message };\n }\n }\n\n async followUser(userId: string): Promise<PostResult> {\n try {\n const page = await this.ensureBrowser();\n // userId here may be a handle in browser mode\n await page.goto(`${X_BASE}/${userId}`, { waitUntil: \"domcontentloaded\" });\n await page.waitForTimeout(2000);\n\n const followButton = page.locator('[data-testid$=\"-follow\"]').first();\n await followButton.click();\n await page.waitForTimeout(1000);\n\n logInteraction({\n id: `int-${Date.now()}`,\n timestamp: new Date().toISOString(),\n type: \"follow\",\n targetUserId: userId,\n creditsUsed: 0,\n success: true,\n });\n\n await this.saveSession();\n return { success: true };\n } catch (error) {\n return { success: false, error: (error as Error).message };\n }\n }\n\n async unfollowUser(userId: string): Promise<PostResult> {\n try {\n const page = await this.ensureBrowser();\n await page.goto(`${X_BASE}/${userId}`, { waitUntil: \"domcontentloaded\" });\n await page.waitForTimeout(2000);\n\n const unfollowButton = page.locator('[data-testid$=\"-unfollow\"]').first();\n await unfollowButton.click();\n await page.waitForTimeout(1000);\n\n // Confirm unfollow\n await page.locator('[data-testid=\"confirmationSheetConfirm\"]').click();\n await page.waitForTimeout(1000);\n\n await this.saveSession();\n return { success: true };\n } catch (error) {\n return { success: false, error: (error as Error).message };\n }\n }\n\n async getTimeline(options?: TimelineOptions): Promise<Tweet[]> {\n try {\n const page = await this.ensureBrowser();\n await page.goto(X_BASE, { waitUntil: \"domcontentloaded\" });\n await page.waitForTimeout(3000);\n\n const tweets = await this.scrapeTweets(page, options?.count ?? 20);\n return tweets;\n } catch (error) {\n logger.error(\"Failed to read timeline via browser\", error);\n return [];\n }\n }\n\n async getMentions(options?: TimelineOptions): Promise<Tweet[]> {\n try {\n const page = await this.ensureBrowser();\n await page.goto(`${X_BASE}/notifications/mentions`, {\n waitUntil: \"domcontentloaded\",\n });\n await page.waitForTimeout(3000);\n\n const tweets = await this.scrapeTweets(page, options?.count ?? 20);\n return tweets;\n } catch (error) {\n logger.error(\"Failed to read mentions via browser\", error);\n return [];\n }\n }\n\n async searchTweets(query: string, options?: SearchOptions): Promise<Tweet[]> {\n try {\n const page = await this.ensureBrowser();\n const encodedQuery = encodeURIComponent(query);\n await page.goto(`${X_BASE}/search?q=${encodedQuery}&f=live`, {\n waitUntil: \"domcontentloaded\",\n });\n await page.waitForTimeout(3000);\n\n const tweets = await this.scrapeTweets(page, options?.count ?? 20);\n return tweets;\n } catch (error) {\n logger.error(\"Failed to search via browser\", error);\n return [];\n }\n }\n\n async getProfile(handle: string): Promise<UserProfile> {\n const page = await this.ensureBrowser();\n await page.goto(`${X_BASE}/${handle}`, { waitUntil: \"domcontentloaded\" });\n await page.waitForTimeout(3000);\n\n const name =\n (await page\n .locator('[data-testid=\"UserName\"] span')\n .first()\n .textContent()) ?? handle;\n\n const bio =\n (await page\n .locator('[data-testid=\"UserDescription\"]')\n .textContent()\n .catch(() => \"\")) ?? \"\";\n\n // Parse follower/following counts from the profile page\n const followersText =\n (await page\n .locator(`a[href=\"/${handle}/verified_followers\"] span`)\n .first()\n .textContent()\n .catch(() => \"0\")) ?? \"0\";\n\n const followingText =\n (await page\n .locator(`a[href=\"/${handle}/following\"] span`)\n .first()\n .textContent()\n .catch(() => \"0\")) ?? \"0\";\n\n await this.saveSession();\n\n return {\n id: handle,\n handle,\n name,\n bio,\n followersCount: parseInt(followersText.replace(/[,K.M]/g, \"\")) || 0,\n followingCount: parseInt(followingText.replace(/[,K.M]/g, \"\")) || 0,\n tweetCount: 0,\n verified: false,\n };\n }\n\n private async scrapeTweets(page: Page, count: number): Promise<Tweet[]> {\n const tweets: Tweet[] = [];\n\n const articles = page.locator('article[data-testid=\"tweet\"]');\n const articleCount = await articles.count();\n\n for (let i = 0; i < Math.min(articleCount, count); i++) {\n try {\n const article = articles.nth(i);\n\n const tweetText =\n (await article\n .locator('[data-testid=\"tweetText\"]')\n .textContent()\n .catch(() => \"\")) ?? \"\";\n\n const userLink = article\n .locator('a[role=\"link\"][href*=\"/\"]')\n .first();\n const href = (await userLink.getAttribute(\"href\").catch(() => \"\")) ?? \"\";\n const authorHandle = href.replace(\"/\", \"\");\n\n const time = article.locator(\"time\").first();\n const datetime = (await time.getAttribute(\"datetime\").catch(() => \"\")) ?? \"\";\n\n tweets.push({\n id: `browser-${Date.now()}-${i}`,\n text: tweetText,\n authorId: authorHandle,\n authorHandle,\n createdAt: datetime,\n });\n } catch {\n continue;\n }\n }\n\n return tweets;\n }\n\n async close(): Promise<void> {\n if (this.page) await this.page.close().catch(() => {});\n if (this.context) await this.context.close().catch(() => {});\n if (this.browser) await this.browser.close().catch(() => {});\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
executeAction,
|
|
3
|
-
executeActions,
|
|
4
|
-
parseActions
|
|
5
|
-
} from "./chunk-H2N5G6R7.js";
|
|
6
|
-
import "./chunk-ZMTC7BYD.js";
|
|
7
|
-
import "./chunk-4POAJONO.js";
|
|
8
|
-
import "./chunk-UINSD4FT.js";
|
|
9
|
-
import "./chunk-B6RPMDML.js";
|
|
10
|
-
import "./chunk-AIEXQCQS.js";
|
|
11
|
-
import "./chunk-QOKQ5OTU.js";
|
|
12
|
-
import "./chunk-EBO4F5NU.js";
|
|
13
|
-
import "./chunk-53YLFYJF.js";
|
|
14
|
-
export {
|
|
15
|
-
executeAction,
|
|
16
|
-
executeActions,
|
|
17
|
-
parseActions
|
|
18
|
-
};
|
|
19
|
-
//# sourceMappingURL=decision-engine-SO33N7CT.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/runtime/heartbeat.ts"],"sourcesContent":["import { existsSync, unlinkSync, writeFileSync, readFileSync } from \"node:fs\";\nimport { logger } from \"../utils/logger.js\";\nimport { loadConfig } from \"../utils/config.js\";\nimport { paths } from \"../utils/paths.js\";\nimport { getXClient } from \"../x-client/index.js\";\nimport { flushQueue } from \"../scheduler/queue.js\";\nimport { buildSystemPrompt, buildHeartbeatUserMessage, buildReflectionPrompt } from \"./prompt-builder.js\";\nimport { generateResponse } from \"./llm.js\";\nimport { parseActions, executeActions, type ActionResult } from \"./decision-engine.js\";\nimport { addLearning } from \"../memory/index.js\";\nimport { loadStrategy, saveStrategy } from \"../memory/strategy.js\";\nimport { loadIdentity } from \"../identity/index.js\";\n\nlet running = false;\n\nexport function isRunning(): boolean {\n return running;\n}\n\nexport function requestStop(): void {\n writeFileSync(paths.stopSignal, \"stop\");\n logger.info(\"Stop signal sent.\");\n}\n\nfunction shouldStop(): boolean {\n if (existsSync(paths.stopSignal)) {\n unlinkSync(paths.stopSignal);\n return true;\n }\n return false;\n}\n\nfunction writePid(): void {\n writeFileSync(paths.runtimePid, String(process.pid));\n}\n\nfunction clearPid(): void {\n if (existsSync(paths.runtimePid)) {\n unlinkSync(paths.runtimePid);\n }\n}\n\nexport function getRunningPid(): number | null {\n if (!existsSync(paths.runtimePid)) return null;\n const pid = parseInt(readFileSync(paths.runtimePid, \"utf-8\").trim(), 10);\n if (isNaN(pid)) return null;\n\n // Check if process is actually running\n try {\n process.kill(pid, 0);\n return pid;\n } catch {\n // Process not running, clean up stale PID\n clearPid();\n return null;\n }\n}\n\nexport async function startHeartbeatLoop(): Promise<void> {\n // Check if already running\n const existingPid = getRunningPid();\n if (existingPid) {\n throw new Error(`Spora is already running (PID ${existingPid}). Run \\`spora stop\\` first.`);\n }\n\n running = true;\n writePid();\n\n const config = loadConfig();\n const intervalMs = config.runtime?.heartbeatIntervalMs ?? 300_000;\n const maxActions = config.runtime?.actionsPerHeartbeat ?? 3;\n\n logger.info(`Spora agent starting. Heartbeat interval: ${intervalMs / 1000}s, max actions: ${maxActions}`);\n console.log(`\\nSpora agent is running (PID ${process.pid})`);\n console.log(`Heartbeat every ${Math.round(intervalMs / 60_000)} minutes`);\n console.log(`Press Ctrl+C or run \\`spora stop\\` to stop.\\n`);\n\n // Handle graceful shutdown\n const shutdown = () => {\n logger.info(\"Shutting down...\");\n running = false;\n clearPid();\n process.exit(0);\n };\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n\n // Clean any stale stop signal\n if (existsSync(paths.stopSignal)) {\n unlinkSync(paths.stopSignal);\n }\n\n let heartbeatCount = 0;\n\n while (running) {\n heartbeatCount++;\n logger.info(`=== Heartbeat #${heartbeatCount} ===`);\n\n try {\n await runHeartbeat(maxActions, heartbeatCount);\n } catch (error) {\n logger.error(\"Heartbeat error\", error);\n console.error(`Heartbeat #${heartbeatCount} failed: ${(error as Error).message}`);\n }\n\n // Check for stop signal\n if (shouldStop()) {\n logger.info(\"Stop signal received.\");\n break;\n }\n\n // Sleep with jitter\n const jitter = Math.floor(Math.random() * intervalMs * 0.3);\n const sleepMs = intervalMs + jitter;\n logger.info(`Sleeping ${Math.round(sleepMs / 1000)}s until next heartbeat...`);\n\n // Sleep in chunks so we can check for stop signals\n const chunkMs = 10_000;\n let slept = 0;\n while (slept < sleepMs && running) {\n await new Promise((r) => setTimeout(r, Math.min(chunkMs, sleepMs - slept)));\n slept += chunkMs;\n if (shouldStop()) {\n running = false;\n break;\n }\n }\n }\n\n clearPid();\n logger.info(\"Spora agent stopped.\");\n console.log(\"\\nSpora agent stopped.\");\n}\n\nasync function runHeartbeat(maxActions: number, heartbeatCount: number): Promise<void> {\n // 1. Flush any queued posts\n logger.info(\"Checking queue...\");\n try {\n const flushed = await flushQueue();\n if (flushed.posted > 0) {\n logger.info(`Flushed ${flushed.posted} queued posts.`);\n }\n } catch (error) {\n logger.warn(`Queue flush failed: ${(error as Error).message}`);\n }\n\n // 2. Read timeline and mentions for context\n logger.info(\"Reading timeline and mentions...\");\n const client = await getXClient();\n\n let timeline: Awaited<ReturnType<typeof client.getTimeline>> = [];\n let mentions: Awaited<ReturnType<typeof client.getMentions>> = [];\n\n try {\n timeline = await client.getTimeline({ count: 20 });\n } catch (error) {\n logger.warn(`Timeline read failed: ${(error as Error).message}`);\n }\n\n try {\n mentions = await client.getMentions({ count: 10 });\n } catch (error) {\n logger.warn(`Mentions read failed: ${(error as Error).message}`);\n }\n\n // 3. Build prompts\n const systemPrompt = buildSystemPrompt();\n const userMessage = buildHeartbeatUserMessage(timeline, mentions);\n\n // 4. Ask LLM for decisions\n logger.info(\"Asking LLM for decisions...\");\n const response = await generateResponse(systemPrompt, userMessage);\n\n // 5. Parse and execute actions\n const actions = parseActions(response.content);\n if (actions.length === 0) {\n logger.info(\"LLM returned no actions.\");\n return;\n }\n\n // Limit to max actions per heartbeat\n const limitedActions = actions.slice(0, maxActions);\n logger.info(`Executing ${limitedActions.length} action(s)...`);\n\n const results = await executeActions(limitedActions);\n\n // 6. Log results\n for (const result of results) {\n if (result.success) {\n logger.info(` [OK] ${result.action}${result.detail ? `: ${result.detail}` : \"\"}`);\n } else {\n logger.warn(` [FAIL] ${result.action}: ${result.error}`);\n }\n }\n\n logger.info(`Heartbeat complete. ${results.filter((r) => r.success).length}/${results.length} actions succeeded.`);\n\n // 7. Reflection phase — every 3rd heartbeat\n if (heartbeatCount % 3 === 0) {\n try {\n logger.info(\"Running reflection phase...\");\n const reflectionPrompt = buildReflectionPrompt(results);\n const reflectionResponse = await generateResponse(\n `You are ${loadIdentity().name}. Reflect honestly on your performance.`,\n reflectionPrompt,\n );\n\n const jsonMatch = reflectionResponse.content.match(/\\{[\\s\\S]*\\}/);\n if (jsonMatch) {\n try {\n const reflection = JSON.parse(jsonMatch[0]);\n if (reflection.learning && reflection.learning !== \"null\") {\n addLearning(reflection.learning, \"reflection\", [\"heartbeat\", \"performance\"]);\n logger.info(`Reflection learning: ${reflection.learning}`);\n }\n if (reflection.strategyUpdate && reflection.strategyUpdate !== \"null\") {\n const strategy = loadStrategy();\n strategy.experiments.push({\n description: reflection.strategyUpdate,\n status: \"pending\",\n });\n strategy.lastUpdated = new Date().toISOString();\n saveStrategy(strategy);\n logger.info(`Strategy update: ${reflection.strategyUpdate}`);\n }\n } catch {\n // Couldn't parse reflection JSON\n }\n }\n } catch (err) {\n logger.warn(`Reflection failed: ${(err as Error).message}`);\n }\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/init.ts","../src/x-client/profile-updater.ts"],"sourcesContent":["import { input, select, confirm, password as passwordPrompt } from \"@inquirer/prompts\";\nimport chalk from \"chalk\";\nimport { sporaExists, ensureDirectories } from \"./utils/paths.js\";\nimport { createDefaultConfig, saveConfig } from \"./utils/config.js\";\nimport { saveCredentials, type XCredentials } from \"./utils/crypto.js\";\nimport { loadIdentity } from \"./identity/index.js\";\nimport { updateXProfile } from \"./x-client/profile-updater.js\";\n\n/**\n * Fetch identity from token and save locally\n */\nasync function syncIdentityFromToken(token: string): Promise<void> {\n console.log(chalk.gray(\"Connecting to spora.dev...\\n\"));\n\n const apiUrl = process.env.SPORA_API_URL || \"https://www.spora.social\";\n const response = await fetch(`${apiUrl}/api/v1/connect`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ token }),\n });\n\n if (!response.ok) {\n const errData = await response.json().catch(() => ({}));\n throw new Error(errData.error || `Connection failed: ${response.statusText}`);\n }\n\n const data = await response.json();\n\n if (!data.identity) {\n throw new Error(\"No Spore identity found for this token\");\n }\n\n // Merge media fields\n if (data.media) {\n if (data.media.profileImage) data.identity.profileImage = data.media.profileImage;\n if (data.media.bannerImage) data.identity.bannerImage = data.media.bannerImage;\n }\n\n const { saveIdentity } = await import(\"./identity/index.js\");\n saveIdentity(data.identity);\n\n console.log(chalk.green(`✓ Connected to Spore: ${data.identity.name} (@${data.identity.handle})\\n`));\n\n // Save README if provided\n if (data.readme) {\n const { writeFileSync } = await import(\"node:fs\");\n const { paths } = await import(\"./utils/paths.js\");\n const { join, dirname } = await import(\"node:path\");\n const readmePath = join(dirname(paths.identity), \"IDENTITY.md\");\n writeFileSync(readmePath, data.readme, \"utf-8\");\n console.log(chalk.green(\"✓ Saved identity README\\n\"));\n }\n\n // Save connection token to config\n const { existsSync } = await import(\"node:fs\");\n const { paths } = await import(\"./utils/paths.js\");\n if (existsSync(paths.config)) {\n const { loadConfig, saveConfig } = await import(\"./utils/config.js\");\n const config = loadConfig();\n config.connection = {\n token,\n apiEndpoint: process.env.SPORA_API_URL || \"https://www.spora.social/api/v1\",\n configVersion: config.connection?.configVersion ?? 0,\n };\n saveConfig(config);\n }\n}\n\n/**\n * Login flow: paste token → sync identity → open chat (keys already saved locally)\n */\nasync function loginFlow(): Promise<void> {\n console.log(chalk.bold(\"\\n━━━ Login to Existing Spore ━━━\\n\"));\n console.log(chalk.gray(\"Paste your setup token from spora.dev\"));\n console.log(chalk.gray(\"(It looks like: spora_7e636ac0...)\\n\"));\n\n const token = await input({\n message: \"Setup token:\",\n validate: (val) => val.length > 0 ? true : \"Token is required\",\n });\n\n ensureDirectories();\n\n try {\n await syncIdentityFromToken(token.trim());\n } catch (error) {\n console.log(chalk.red(`\\n✗ ${(error as Error).message}\\n`));\n console.log(chalk.yellow(\"Please check your token and try again.\\n\"));\n process.exit(1);\n }\n\n console.log(chalk.green(\"✓ Logged in!\\n\"));\n console.log(chalk.gray(\"Opening chat interface...\\n\"));\n\n try {\n const { startWebChat } = await import(\"./web-chat/index.js\");\n await startWebChat();\n } catch (error) {\n console.log(chalk.yellow(`Could not start chat interface: ${(error as Error).message}\\n`));\n console.log(chalk.gray(\"You can start it manually with: spora chat\\n\"));\n }\n}\n\n/**\n * Prompt for Anthropic API key and X credentials\n */\nasync function setupKeys(): Promise<void> {\n // DeepSeek key\n console.log(chalk.bold(\"\\n━━━ DeepSeek API Key ━━━\\n\"));\n console.log(chalk.gray(\"Your Spore uses DeepSeek to think and make decisions.\"));\n console.log(chalk.gray(\"Get your API key at: \") + chalk.cyan(\"https://platform.deepseek.com/api_keys\\n\"));\n\n const llmKey = await passwordPrompt({\n message: \"DeepSeek API Key:\",\n mask: \"*\",\n validate: (val: string) => val.length > 0 ? true : \"API key is required\",\n });\n\n const { paths } = await import(\"./utils/paths.js\");\n const { writeFileSync } = await import(\"node:fs\");\n writeFileSync(paths.llmKey, llmKey, \"utf-8\");\n console.log(chalk.green(\"✓ DeepSeek API key saved\\n\"));\n\n // X credentials\n console.log(chalk.bold(\"\\n━━━ Connect Your X Account ━━━\\n\"));\n console.log(chalk.gray(\"Your Spore needs OAuth 1.0a credentials for full X API access.\"));\n console.log(chalk.gray(\"This gives your agent the power to read timelines, post tweets, reply, like, and follow.\\n\"));\n console.log(chalk.cyan(\"How to get these credentials:\"));\n console.log(chalk.gray(\" 1. Go to: \") + chalk.cyan(\"https://developer.x.com/en/portal/dashboard\"));\n console.log(chalk.gray(\" 2. Create or select your app\"));\n console.log(chalk.gray(\" 3. Go to \\\"Keys and tokens\\\" tab\"));\n console.log(chalk.gray(\" 4. Copy all 4 credentials below\\n\"));\n console.log(chalk.yellow(\"Note: You need X Pro account ($200/mo) for posting access.\\n\"));\n\n const apiKey = await passwordPrompt({\n message: \"X API Key (Consumer Key):\",\n mask: \"*\",\n validate: (val: string) => val.length > 0 ? true : \"API Key is required\",\n });\n\n const apiSecret = await passwordPrompt({\n message: \"X API Secret (Consumer Secret):\",\n mask: \"*\",\n validate: (val: string) => val.length > 0 ? true : \"API Secret is required\",\n });\n\n const accessToken = await passwordPrompt({\n message: \"X Access Token:\",\n mask: \"*\",\n validate: (val: string) => val.length > 0 ? true : \"Access Token is required\",\n });\n\n const accessTokenSecret = await passwordPrompt({\n message: \"X Access Token Secret:\",\n mask: \"*\",\n validate: (val: string) => val.length > 0 ? true : \"Access Token Secret is required\",\n });\n\n const bearerToken = await passwordPrompt({\n message: \"X Bearer Token:\",\n mask: \"*\",\n validate: (val: string) => val.length > 0 ? true : \"Bearer Token is required\",\n });\n\n saveCredentials({\n method: \"api\",\n apiKey,\n apiSecret,\n accessToken,\n accessTokenSecret,\n bearerToken,\n });\n console.log(chalk.green(\"✓ X API credentials saved (encrypted)\\n\"));\n}\n\n/**\n * Show completion message and open chat\n */\nasync function showDoneAndOpenChat(): Promise<void> {\n console.log(chalk.green(\"\\n╔═══════════════════════════════════════╗\"));\n console.log(chalk.green.bold(\"║ Setup Complete! ║\"));\n console.log(chalk.green(\"╚═══════════════════════════════════════╝\\n\"));\n\n console.log(chalk.bold.cyan(\"━━━ Your Spore is Ready! ━━━\\n\"));\n console.log(chalk.gray(\"Opening chat interface...\\n\"));\n\n try {\n const { startWebChat } = await import(\"./web-chat/index.js\");\n await startWebChat();\n } catch (error) {\n console.log(chalk.yellow(`Could not start chat interface: ${(error as Error).message}\\n`));\n console.log(chalk.gray(\"You can start it manually with: spora chat\\n\"));\n }\n\n console.log(chalk.bold(\"Quick Start:\\n\"));\n console.log(chalk.cyan(\" spora chat\"));\n console.log(chalk.gray(\" → Talk to your Spore, tell it what to post, how to behave\\n\"));\n console.log(chalk.bold(\"Or start the autonomous agent:\\n\"));\n console.log(chalk.cyan(\" spora start\"));\n console.log(chalk.gray(\" → Your Spore will post and engage autonomously\\n\"));\n console.log(chalk.bold(\"Other commands:\\n\"));\n console.log(chalk.cyan(\" spora create \") + chalk.gray(\"# Create a personality\"));\n console.log(chalk.cyan(\" spora post <text> \") + chalk.gray(\"# Make your Spore post\"));\n console.log(chalk.cyan(\" spora agent-status \") + chalk.gray(\"# Check if agent is running\"));\n console.log(chalk.cyan(\" spora stop \") + chalk.gray(\"# Stop the agent\"));\n console.log(chalk.cyan(\" spora --help \") + chalk.gray(\"# See all commands\\n\"));\n}\n\nexport async function runInit(token?: string): Promise<void> {\n console.log(chalk.bold.cyan(\"\\n╔════════════════════════════════════════╗\"));\n console.log(chalk.bold.cyan(\"║ Welcome to Spora CLI Setup ║\"));\n console.log(chalk.bold.cyan(\"╚════════════════════════════════════════╝\\n\"));\n\n // If token provided via --token flag, this is a new user from the website → full setup\n if (token) {\n ensureDirectories();\n\n console.log(chalk.bold(\"\\n━━━ Connecting Your Spore ━━━\\n\"));\n try {\n await syncIdentityFromToken(token);\n } catch (error) {\n console.log(chalk.red(`\\n✗ ${(error as Error).message}\\n`));\n console.log(chalk.yellow(\"Please check your token and try again.\\n\"));\n process.exit(1);\n }\n\n await setupKeys();\n\n // Update X profile\n console.log(chalk.bold(\"\\n━━━ Updating Your X Profile ━━━\\n\"));\n console.log(chalk.gray(\"Setting up profile picture, banner, and bio to match your Spore...\\n\"));\n try {\n const identity = loadIdentity();\n const result = await updateXProfile(identity);\n if (result.success) {\n console.log(chalk.green(\"✓ Profile updated successfully!\\n\"));\n if (result.updated.length > 0) {\n console.log(chalk.cyan(\"Updated:\"));\n for (const field of result.updated) {\n console.log(chalk.gray(` • ${field}`));\n }\n console.log();\n }\n }\n if (result.errors.length > 0) {\n console.log(chalk.yellow(\"\\nSome updates failed:\"));\n for (const err of result.errors) {\n console.log(chalk.gray(` • ${err}`));\n }\n console.log();\n }\n } catch (error) {\n console.log(chalk.yellow(`Could not update profile: ${(error as Error).message}\\n`));\n console.log(chalk.gray(\"You can manually update your X profile later.\\n\"));\n }\n\n const config = createDefaultConfig({ xMethod: \"api\", xApiTier: \"basic\" });\n config.llm = { provider: \"deepseek\", model: \"deepseek-chat\" };\n config.runtime = { heartbeatIntervalMs: 300_000, actionsPerHeartbeat: 3, enabled: true };\n config.connection = {\n token,\n apiEndpoint: process.env.SPORA_API_URL || \"https://www.spora.social/api/v1\",\n configVersion: 0,\n };\n saveConfig(config);\n\n await showDoneAndOpenChat();\n return;\n }\n\n // No token provided — ask what they want to do\n const action = await select({\n message: \"What would you like to do?\",\n choices: [\n { name: \"Create a new Spore\", value: \"new\" },\n { name: \"Login to existing Spore\", value: \"login\" },\n ],\n });\n\n if (action === \"login\") {\n await loginFlow();\n return;\n }\n\n // \"new\" — full new Spore creation (no token, manual setup)\n ensureDirectories();\n\n await setupKeys();\n\n // Update X profile\n console.log(chalk.bold(\"\\n━━━ Updating Your X Profile ━━━\\n\"));\n console.log(chalk.gray(\"Setting up profile picture, banner, and bio to match your Spore...\\n\"));\n try {\n const identity = loadIdentity();\n const result = await updateXProfile(identity);\n if (result.success) {\n console.log(chalk.green(\"✓ Profile updated successfully!\\n\"));\n if (result.updated.length > 0) {\n console.log(chalk.cyan(\"Updated:\"));\n for (const field of result.updated) {\n console.log(chalk.gray(` • ${field}`));\n }\n console.log();\n }\n }\n if (result.errors.length > 0) {\n console.log(chalk.yellow(\"\\nSome updates failed:\"));\n for (const err of result.errors) {\n console.log(chalk.gray(` • ${err}`));\n }\n console.log();\n }\n } catch (error) {\n console.log(chalk.yellow(`Could not update profile: ${(error as Error).message}\\n`));\n console.log(chalk.gray(\"You can manually update your X profile later.\\n\"));\n }\n\n const config = createDefaultConfig({ xMethod: \"api\", xApiTier: \"basic\" });\n config.llm = { provider: \"deepseek\", model: \"deepseek-chat\" };\n config.runtime = { heartbeatIntervalMs: 300_000, actionsPerHeartbeat: 3, enabled: true };\n saveConfig(config);\n\n await showDoneAndOpenChat();\n}\n","/**\n * X Profile Updater\n * Updates X profile to match Spore identity (name, bio, profile pic, banner)\n */\n\nimport { TwitterApi } from \"twitter-api-v2\";\nimport sharp from \"sharp\";\nimport type { Identity } from \"../identity/schema.js\";\nimport { loadCredentials } from \"../utils/crypto.js\";\n\ninterface ProfileUpdateResult {\n success: boolean;\n updated: string[];\n errors: string[];\n}\n\n/**\n * Update X profile to match Spore identity\n * Requires OAuth 1.0a credentials\n */\nexport async function updateXProfile(identity: Identity): Promise<ProfileUpdateResult> {\n const result: ProfileUpdateResult = {\n success: false,\n updated: [],\n errors: [],\n };\n\n try {\n const creds = loadCredentials();\n if (creds.method !== \"api\") {\n result.errors.push(\"API credentials required\");\n return result;\n }\n\n // Create Twitter API client with OAuth 1.0a credentials\n const client = new TwitterApi({\n appKey: creds.apiKey!,\n appSecret: creds.apiSecret!,\n accessToken: creds.accessToken!,\n accessSecret: creds.accessTokenSecret!,\n });\n\n // Update profile name and bio (username separately to avoid breaking on failure)\n try {\n console.log(`Updating name to: ${identity.name}`);\n console.log(`Updating bio to: ${identity.bio.substring(0, 60)}...`);\n await client.v1.updateAccountProfile({\n name: identity.name,\n description: identity.bio,\n });\n result.updated.push(\"name\", \"bio\");\n console.log(\"Name and bio updated successfully\");\n } catch (error) {\n console.error(\"Name/bio update error:\", error);\n result.errors.push(`Failed to update name/bio: ${(error as Error).message}`);\n }\n\n // Try to update username separately (optional, may fail if taken or restricted)\n if (identity.handle) {\n try {\n console.log(`Attempting to update username to: @${identity.handle}`);\n await client.v1.updateAccountProfile({\n screen_name: identity.handle,\n });\n result.updated.push(\"username\");\n console.log(\"Username updated successfully\");\n } catch (error) {\n // Don't fail the whole update if username change fails\n console.warn(`Could not update username: ${(error as Error).message}`);\n }\n }\n\n // Update profile image if available\n if (identity.profileImage) {\n try {\n console.log(`Downloading profile image from: ${identity.profileImage.substring(0, 60)}...`);\n let imageBuffer = await downloadImage(identity.profileImage);\n console.log(`Downloaded ${(imageBuffer.length / 1024 / 1024).toFixed(2)}MB`);\n\n // Check image dimensions - Twitter requires min 400x400\n const metadata = await sharp(imageBuffer).metadata();\n console.log(`Image dimensions: ${metadata.width}x${metadata.height}`);\n\n if (!metadata.width || !metadata.height || metadata.width < 400 || metadata.height < 400) {\n throw new Error(`Image too small (${metadata.width}x${metadata.height}). Twitter requires minimum 400x400 pixels.`);\n }\n\n // Compress if needed (Twitter profile image limit: 2MB)\n const MAX_PROFILE_SIZE = 2 * 1024 * 1024; // 2MB\n imageBuffer = await compressImageIfNeeded(imageBuffer, MAX_PROFILE_SIZE, \"Profile\");\n\n console.log(`Uploading profile image to X...`);\n await client.v1.updateAccountProfileImage(imageBuffer);\n result.updated.push(\"profile_image\");\n console.log(\"Profile image updated successfully\");\n } catch (error) {\n console.error(\"Profile image error:\", error);\n result.errors.push(`Failed to update profile image: ${(error as Error).message}`);\n }\n } else {\n console.log(\"No profile image URL in identity\");\n }\n\n // Update banner image if available\n if (identity.bannerImage) {\n try {\n console.log(`Downloading banner image from: ${identity.bannerImage.substring(0, 60)}...`);\n let imageBuffer = await downloadImage(identity.bannerImage);\n console.log(`Downloaded ${(imageBuffer.length / 1024 / 1024).toFixed(2)}MB`);\n\n // Compress if needed (Twitter banner limit: 5MB)\n const MAX_BANNER_SIZE = 5 * 1024 * 1024; // 5MB\n imageBuffer = await compressImageIfNeeded(imageBuffer, MAX_BANNER_SIZE, \"Banner\");\n\n console.log(`Uploading banner image to X...`);\n await client.v1.updateAccountProfileBanner(imageBuffer);\n result.updated.push(\"banner_image\");\n console.log(\"Banner image updated successfully\");\n } catch (error) {\n console.error(\"Banner image error:\", error);\n result.errors.push(`Failed to update banner: ${(error as Error).message}`);\n }\n } else {\n console.log(\"No banner image URL in identity\");\n }\n\n result.success = result.updated.length > 0;\n return result;\n } catch (error) {\n result.errors.push((error as Error).message);\n return result;\n }\n}\n\n/**\n * Download image from URL and return as Buffer\n */\nasync function downloadImage(url: string): Promise<Buffer> {\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error(`Failed to download image: ${response.statusText}`);\n }\n const arrayBuffer = await response.arrayBuffer();\n return Buffer.from(arrayBuffer);\n}\n\n/**\n * Compress image if it exceeds size limit by resizing\n * @param buffer Original image buffer\n * @param maxSizeBytes Maximum allowed size in bytes\n * @param type \"profile\" or \"banner\" for logging\n */\nasync function compressImageIfNeeded(\n buffer: Buffer,\n maxSizeBytes: number,\n type: string\n): Promise<Buffer> {\n if (buffer.length <= maxSizeBytes) {\n return buffer;\n }\n\n console.log(\n `${type} image is ${(buffer.length / 1024 / 1024).toFixed(2)}MB, resizing to fit ${(maxSizeBytes / 1024 / 1024).toFixed(0)}MB limit...`\n );\n\n // Calculate scale factor to fit within size limit\n const scaleFactor = Math.sqrt(maxSizeBytes / buffer.length) * 0.85; // 85% of target for safety\n\n // Get current dimensions and calculate new size\n const metadata = await sharp(buffer).metadata();\n const newWidth = Math.floor((metadata.width || 1000) * scaleFactor);\n\n // Resize and convert to JPEG with good quality\n const compressed = await sharp(buffer)\n .resize(newWidth, null, { fit: \"inside\", withoutEnlargement: true })\n .jpeg({ quality: 90, progressive: true })\n .toBuffer();\n\n console.log(\n `Resized ${type} image from ${(buffer.length / 1024 / 1024).toFixed(2)}MB to ${(compressed.length / 1024 / 1024).toFixed(2)}MB`\n );\n\n return compressed;\n}\n"],"mappings":"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","names":["paths","saveConfig","config"]}
|
package/dist/llm-3LSNADSR.js
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
chat,
|
|
3
|
-
generateResponse,
|
|
4
|
-
getLLMApiKey,
|
|
5
|
-
hasLLMKey
|
|
6
|
-
} from "./chunk-55XPDJ6P.js";
|
|
7
|
-
import "./chunk-B6RPMDML.js";
|
|
8
|
-
import "./chunk-QOKQ5OTU.js";
|
|
9
|
-
import "./chunk-53YLFYJF.js";
|
|
10
|
-
export {
|
|
11
|
-
chat,
|
|
12
|
-
generateResponse,
|
|
13
|
-
getLLMApiKey,
|
|
14
|
-
hasLLMKey
|
|
15
|
-
};
|
|
16
|
-
//# sourceMappingURL=llm-3LSNADSR.js.map
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
buildChatPrompt,
|
|
3
|
-
buildHeartbeatUserMessage,
|
|
4
|
-
buildReflectionPrompt,
|
|
5
|
-
buildSystemPrompt,
|
|
6
|
-
buildTrainingChatPrompt
|
|
7
|
-
} from "./chunk-LKCYTFWN.js";
|
|
8
|
-
import "./chunk-UM57WU5I.js";
|
|
9
|
-
import "./chunk-YLJVFCT4.js";
|
|
10
|
-
import "./chunk-UINSD4FT.js";
|
|
11
|
-
import "./chunk-B6RPMDML.js";
|
|
12
|
-
import "./chunk-AIEXQCQS.js";
|
|
13
|
-
import "./chunk-QOKQ5OTU.js";
|
|
14
|
-
import "./chunk-EBO4F5NU.js";
|
|
15
|
-
import "./chunk-53YLFYJF.js";
|
|
16
|
-
export {
|
|
17
|
-
buildChatPrompt,
|
|
18
|
-
buildHeartbeatUserMessage,
|
|
19
|
-
buildReflectionPrompt,
|
|
20
|
-
buildSystemPrompt,
|
|
21
|
-
buildTrainingChatPrompt
|
|
22
|
-
};
|
|
23
|
-
//# sourceMappingURL=prompt-builder-3LQFX6QK.js.map
|
package/dist/queue-CXMLAQ6X.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
addToQueue,
|
|
3
|
-
flushQueue,
|
|
4
|
-
showQueue
|
|
5
|
-
} from "./chunk-4POAJONO.js";
|
|
6
|
-
import "./chunk-B6RPMDML.js";
|
|
7
|
-
import "./chunk-QOKQ5OTU.js";
|
|
8
|
-
import "./chunk-53YLFYJF.js";
|
|
9
|
-
export {
|
|
10
|
-
addToQueue,
|
|
11
|
-
flushQueue,
|
|
12
|
-
showQueue
|
|
13
|
-
};
|
|
14
|
-
//# sourceMappingURL=queue-CXMLAQ6X.js.map
|