@lightcone-ai/daemon 0.9.53 → 0.9.55
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,19 +33,45 @@ export class XhsAdapter {
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
async checkLoginStatus() {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
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
|
+
})()`,
|
|
41
53
|
returnByValue: true,
|
|
42
54
|
});
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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 };
|
|
49
75
|
}
|
|
50
76
|
|
|
51
77
|
async publishImageText({ title, text, tags = [], images = [] }) {
|
|
@@ -168,7 +168,7 @@ export async function getSession(platform, profileDir) {
|
|
|
168
168
|
await existing.cdp.send('Runtime.evaluate', { expression: '1', returnByValue: true }, 3000);
|
|
169
169
|
return existing.cdp;
|
|
170
170
|
} catch {
|
|
171
|
-
console.
|
|
171
|
+
console.error(`[ChromePool] Session for ${platform} is stale, recreating`);
|
|
172
172
|
existing.proc?.kill();
|
|
173
173
|
_sessions.delete(platform);
|
|
174
174
|
}
|
|
@@ -177,7 +177,7 @@ export async function getSession(platform, profileDir) {
|
|
|
177
177
|
if (!profileDir) throw new Error(`No profile dir provided for platform=${platform}. Has the user logged in?`);
|
|
178
178
|
|
|
179
179
|
const port = _nextPort++;
|
|
180
|
-
console.
|
|
180
|
+
console.error(`[ChromePool] Starting Chrome for ${platform} on port ${port}, profile=${profileDir}`);
|
|
181
181
|
const proc = await _spawnChrome(profileDir, port);
|
|
182
182
|
const cdp = await _connectCdp(port);
|
|
183
183
|
|
|
@@ -192,18 +192,30 @@ export async function getSession(platform, profileDir) {
|
|
|
192
192
|
const cookiesFile = path.join(profileDir, 'cookies.json');
|
|
193
193
|
if (existsSync(cookiesFile)) {
|
|
194
194
|
try {
|
|
195
|
-
const
|
|
195
|
+
const rawCookies = JSON.parse(readFileSync(cookiesFile, 'utf8'));
|
|
196
|
+
// Strip read-only fields that Network.setCookies doesn't accept
|
|
197
|
+
const cookies = rawCookies.map(({ name, value, domain, path: p, secure, httpOnly, sameSite, expires, priority }) => {
|
|
198
|
+
const c = { name, value };
|
|
199
|
+
if (domain !== undefined) c.domain = domain;
|
|
200
|
+
if (p !== undefined) c.path = p;
|
|
201
|
+
if (secure !== undefined) c.secure = secure;
|
|
202
|
+
if (httpOnly !== undefined) c.httpOnly = httpOnly;
|
|
203
|
+
if (sameSite !== undefined) c.sameSite = sameSite;
|
|
204
|
+
if (expires !== undefined && expires !== -1) c.expires = expires;
|
|
205
|
+
if (priority !== undefined) c.priority = priority;
|
|
206
|
+
return c;
|
|
207
|
+
});
|
|
196
208
|
await cdp.send('Network.setCookies', { cookies });
|
|
197
|
-
console.
|
|
209
|
+
console.error(`[ChromePool] Injected ${cookies.length} cookies from cookies.json for ${platform}`);
|
|
198
210
|
} catch (err) {
|
|
199
211
|
console.error(`[ChromePool] Failed to inject cookies: ${err.message}`);
|
|
200
212
|
}
|
|
201
213
|
} else {
|
|
202
|
-
console.
|
|
214
|
+
console.error(`[ChromePool] No cookies.json found for ${platform} at ${cookiesFile}`);
|
|
203
215
|
}
|
|
204
216
|
|
|
205
217
|
proc.on('exit', () => {
|
|
206
|
-
console.
|
|
218
|
+
console.error(`[ChromePool] Chrome for ${platform} exited`);
|
|
207
219
|
_sessions.delete(platform);
|
|
208
220
|
});
|
|
209
221
|
|
|
@@ -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 } = 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调试信息:
|
|
161
|
+
content: [{ type: 'text', text: `${label} 未登录或登录已过期。\n调试信息: url=${url}\nprofileDir=${profileDir}\nuserId=${userId} nickname=${nickname}\n请在「连接外部账号」中重新扫码连接。` }],
|
|
162
162
|
isError: true,
|
|
163
163
|
};
|
|
164
164
|
}
|