@lightcone-ai/daemon 0.9.42 → 0.9.44

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lightcone-ai/daemon",
3
- "version": "0.9.42",
3
+ "version": "0.9.44",
4
4
  "type": "module",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -16,36 +16,29 @@ import { WebSocket } from 'ws';
16
16
  export const PLATFORM_CONFIGS = {
17
17
  xhs: {
18
18
  loginUrl: 'https://www.xiaohongshu.com',
19
- isLoggedIn: (cookies) => cookies.some(c => c.name === 'web_session' && c.value?.length > 0),
20
- // Both domain variants to cover host-only and domain cookies
21
- sessionCookies: [
22
- { name: 'web_session', domain: '.xiaohongshu.com' },
23
- { name: 'web_session', domain: 'www.xiaohongshu.com' },
24
- ],
19
+ // Returns current session value (null if not present)
20
+ getSessionValue: (cookies) => cookies.find(c => c.name === 'web_session')?.value ?? null,
21
+ // Login = value exists AND has changed from baseline (real auth replaces anonymous session)
22
+ isLoggedIn: (cookies, baseline) => {
23
+ const val = cookies.find(c => c.name === 'web_session')?.value ?? null;
24
+ return val !== null && val !== baseline;
25
+ },
25
26
  },
26
27
  douyin: {
27
28
  loginUrl: 'https://www.douyin.com',
28
- isLoggedIn: (cookies) => cookies.some(c =>
29
- (c.name === 'sessionid' || c.name === 'sid_guard') && c.value?.length > 0
30
- ),
31
- sessionCookies: [
32
- { name: 'sessionid', domain: '.douyin.com' },
33
- { name: 'sessionid', domain: 'www.douyin.com' },
34
- { name: 'sid_guard', domain: '.douyin.com' },
35
- { name: 'sid_guard', domain: 'www.douyin.com' },
36
- ],
29
+ getSessionValue: (cookies) => cookies.find(c => c.name === 'sessionid')?.value ?? null,
30
+ isLoggedIn: (cookies, baseline) => {
31
+ const val = cookies.find(c => c.name === 'sessionid')?.value ?? null;
32
+ return val !== null && val !== baseline;
33
+ },
37
34
  },
38
35
  kuaishou: {
39
36
  loginUrl: 'https://www.kuaishou.com',
40
- isLoggedIn: (cookies) => cookies.some(c =>
41
- (c.name === 'userId' || c.name === 'passToken') && c.value?.length > 0
42
- ),
43
- sessionCookies: [
44
- { name: 'userId', domain: '.kuaishou.com' },
45
- { name: 'userId', domain: 'www.kuaishou.com' },
46
- { name: 'passToken', domain: '.kuaishou.com' },
47
- { name: 'passToken', domain: 'www.kuaishou.com' },
48
- ],
37
+ getSessionValue: (cookies) => cookies.find(c => c.name === 'passToken')?.value ?? null,
38
+ isLoggedIn: (cookies, baseline) => {
39
+ const val = cookies.find(c => c.name === 'passToken')?.value ?? null;
40
+ return val !== null && val !== baseline;
41
+ },
49
42
  },
50
43
  };
51
44
 
@@ -111,17 +104,11 @@ export class BrowserLoginSession {
111
104
  async start(connection, userId) {
112
105
  this._profileDir = profileDir(this._platform, userId);
113
106
 
114
- // Ensure profile dir exists
107
+ // Wipe the profile dir before each login so stale cookies can't fool the login check.
108
+ // This is safe — these dirs are single-platform dedicated profiles; fresh start is correct.
109
+ try { if (existsSync(this._profileDir)) rmSync(this._profileDir, { recursive: true, force: true }); } catch {}
115
110
  try { mkdirSync(this._profileDir, { recursive: true }); } catch {}
116
111
 
117
- // Delete the Cookies file before Chrome starts so stale session cookies can't fool the login check
118
- for (const cookiePath of [
119
- path.join(this._profileDir, 'Default', 'Cookies'),
120
- path.join(this._profileDir, 'Cookies'),
121
- ]) {
122
- try { if (existsSync(cookiePath)) rmSync(cookiePath, { force: true }); } catch {}
123
- }
124
-
125
112
  // Kill any process holding the CDP port
126
113
  try {
127
114
  if (process.platform !== 'win32') {
@@ -187,7 +174,14 @@ export class BrowserLoginSession {
187
174
 
188
175
  await this.send('Page.navigate', { url: this._config.loginUrl });
189
176
 
190
- this._startPolling(connection);
177
+ // Wait for page to settle, then record baseline session cookie value.
178
+ // XHS sets an anonymous web_session on first visit — we only trigger login_complete
179
+ // when the value CHANGES (real login replaces it with an authenticated session).
180
+ await sleep(4000);
181
+ const baselineCookies = await this.send('Network.getAllCookies', {});
182
+ const baselineSession = this._config.getSessionValue(baselineCookies.cookies ?? []);
183
+
184
+ this._startPolling(connection, baselineSession);
191
185
  }
192
186
 
193
187
  _connect(wsUrl) {
@@ -231,12 +225,12 @@ export class BrowserLoginSession {
231
225
  return result.data;
232
226
  }
233
227
 
234
- async isLoggedIn() {
228
+ async isLoggedIn(baseline) {
235
229
  const result = await this.send('Network.getAllCookies', {});
236
- return this._config.isLoggedIn(result.cookies ?? []);
230
+ return this._config.isLoggedIn(result.cookies ?? [], baseline);
237
231
  }
238
232
 
239
- _startPolling(connection) {
233
+ _startPolling(connection, baselineSession) {
240
234
  let _screenshotInProgress = false;
241
235
  this._screenshotTimer = setInterval(async () => {
242
236
  if (_screenshotInProgress) return;
@@ -253,7 +247,7 @@ export class BrowserLoginSession {
253
247
 
254
248
  this._loginCheckTimer = setInterval(async () => {
255
249
  try {
256
- const loggedIn = await this.isLoggedIn();
250
+ const loggedIn = await this.isLoggedIn(baselineSession);
257
251
  if (loggedIn) {
258
252
  this._stopTimers();
259
253
  connection.send({ type: 'browser:login_complete', platform: this._platform, profileDir: this._profileDir });