@lightcone-ai/daemon 0.9.54 → 0.9.56

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.
@@ -33,24 +33,45 @@ export class XhsAdapter {
33
33
  }
34
34
 
35
35
  async checkLoginStatus() {
36
- // Check injected cookies before navigation
37
- const cookiesResult = await this._cdp.send('Network.getAllCookies', {});
38
- const allCookies = cookiesResult.cookies ?? [];
39
- const xhsCookies = allCookies.filter(c => c.domain?.includes('xiaohongshu.com'));
40
- const webSession = xhsCookies.find(c => c.name === 'web_session');
41
-
42
- // Navigate to publish pageif redirected away, session is expired
43
- await this._cdp.send('Page.navigate', { url: 'https://creator.xiaohongshu.com/publish/publish' });
44
- await sleep(5000);
45
- const result = await this._cdp.send('Runtime.evaluate', {
46
- expression: 'window.location.href',
36
+ const profileDir = process.env.XHS_PROFILE_DIR ?? '(not set)';
37
+
38
+ // Step 1: navigate to www first to establish session context (same as login origin)
39
+ await this._cdp.send('Page.navigate', { url: 'https://www.xiaohongshu.com' });
40
+ await sleep(4000);
41
+
42
+ // Step 2: check login via window.__INITIAL_STATE__ (auto-agent approach more reliable than URL check)
43
+ const stateResult = await this._cdp.send('Runtime.evaluate', {
44
+ expression: `(function() {
45
+ try {
46
+ const state = window.__INITIAL_STATE__ || {};
47
+ const userInfo = state?.user?.userInfo?._rawValue || state?.user?.userInfo || {};
48
+ const userId = userInfo.userId || userInfo.userID || null;
49
+ const nickname = userInfo.nickname || userInfo.nickName || null;
50
+ return JSON.stringify({ userId, nickname });
51
+ } catch(e) { return JSON.stringify({ error: e.message }); }
52
+ })()`,
47
53
  returnByValue: true,
48
54
  });
49
- const url = result.result?.value ?? '';
50
- const profileDir = process.env.XHS_PROFILE_DIR ?? '(not set)';
51
- console.error(`[XhsAdapter] checkLoginStatus url=${url} xhsCookies=${xhsCookies.length} web_session=${webSession ? webSession.value.slice(0, 20) + '...' : 'missing'}`);
52
- const loggedIn = url.includes('creator.xiaohongshu.com/publish/publish');
53
- return { loggedIn, url, profileDir, xhsCookieCount: xhsCookies.length, hasWebSession: !!webSession };
55
+ const stateStr = stateResult.result?.value ?? '{}';
56
+ let stateData = {};
57
+ try { stateData = JSON.parse(stateStr); } catch {}
58
+
59
+ const loggedInViaState = !!(stateData.userId || stateData.nickname);
60
+ console.error(`[XhsAdapter] __INITIAL_STATE__ check: ${stateStr}`);
61
+
62
+ // Step 3: if logged in via state, also verify creator access
63
+ let creatorUrl = '';
64
+ if (loggedInViaState) {
65
+ await this._cdp.send('Page.navigate', { url: 'https://creator.xiaohongshu.com/publish/publish' });
66
+ await sleep(5000);
67
+ const urlResult = await this._cdp.send('Runtime.evaluate', { expression: 'window.location.href', returnByValue: true });
68
+ creatorUrl = urlResult.result?.value ?? '';
69
+ }
70
+
71
+ const loggedIn = loggedInViaState;
72
+ const url = creatorUrl || 'www check only';
73
+ console.error(`[XhsAdapter] checkLoginStatus: loggedIn=${loggedIn} creatorUrl=${creatorUrl} profileDir=${profileDir}`);
74
+ return { loggedIn, url, profileDir, userId: stateData.userId, nickname: stateData.nickname };
54
75
  }
55
76
 
56
77
  async publishImageText({ title, text, tags = [], images = [] }) {
@@ -152,13 +152,13 @@ server.tool(
152
152
  const label = PLATFORM_LABELS[platform] ?? platform;
153
153
  try {
154
154
  const adapter = await getAdapter(platform);
155
- const { loggedIn, url, profileDir, xhsCookieCount, hasWebSession } = await adapter.checkLoginStatus();
155
+ const { loggedIn, url, profileDir, userId, nickname } = await adapter.checkLoginStatus();
156
156
  if (loggedIn) {
157
- return { content: [{ type: 'text', text: `✓ ${label} 已登录,可以发布内容。` }] };
157
+ return { content: [{ type: 'text', text: `✓ ${label} 已登录,用户: ${nickname ?? userId ?? '未知'},可以发布内容。` }] };
158
158
  } else {
159
159
  closeSession(platform);
160
160
  return {
161
- content: [{ type: 'text', text: `${label} 未登录或登录已过期。\n调试信息: 最终URL=${url}\nprofileDir=${profileDir}\nxhsCookies注入数量=${xhsCookieCount} hasWebSession=${hasWebSession}\n请在「连接外部账号」中重新扫码连接。` }],
161
+ content: [{ type: 'text', text: `${label} 未登录或登录已过期。\n调试信息: url=${url}\nprofileDir=${profileDir}\nuserId=${userId} nickname=${nickname}\n请在「连接外部账号」中重新扫码连接。` }],
162
162
  isError: true,
163
163
  };
164
164
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lightcone-ai/daemon",
3
- "version": "0.9.54",
3
+ "version": "0.9.56",
4
4
  "type": "module",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -256,9 +256,16 @@ export class BrowserLoginSession {
256
256
  // Export decrypted cookies to cookies.json so chrome-pool can inject them
257
257
  // without relying on platform-specific keychain encryption (fixes macOS cross-process issue)
258
258
  try {
259
+ // For XHS: also visit creator subdomain so it sets its own session tokens
260
+ // before we snapshot cookies — otherwise creator.xiaohongshu.com rejects the session
261
+ if (this._platform === 'xhs') {
262
+ await this.send('Page.navigate', { url: 'https://creator.xiaohongshu.com' });
263
+ await sleep(4000);
264
+ }
259
265
  const cookieResult = await this.send('Network.getAllCookies', {});
266
+ const baseDomain = new URL(this._config.loginUrl).hostname.split('.').slice(-2).join('.');
260
267
  const cookies = (cookieResult.cookies ?? []).filter(c =>
261
- c.domain.includes(new URL(this._config.loginUrl).hostname.split('.').slice(-2).join('.'))
268
+ c.domain.includes(baseDomain)
262
269
  );
263
270
  writeFileSync(path.join(this._profileDir, 'cookies.json'), JSON.stringify(cookies));
264
271
  console.log(`[BrowserLogin][${this._platform}] Saved ${cookies.length} cookies to cookies.json`);