@lightcone-ai/daemon 0.15.19 → 0.15.21
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.
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { randomUUID } from 'crypto';
|
|
3
3
|
import { spawn } from 'child_process';
|
|
4
|
-
import { accessSync, constants as fsConstants } from 'fs';
|
|
4
|
+
import { accessSync, constants as fsConstants, existsSync, readFileSync, rmSync } from 'fs';
|
|
5
5
|
import http from 'http';
|
|
6
6
|
import net from 'net';
|
|
7
|
+
import path from 'path';
|
|
7
8
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
8
9
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
9
10
|
import { z } from 'zod';
|
|
@@ -86,6 +87,12 @@ class CdpSession {
|
|
|
86
87
|
if (!profileDir) throw new Error('LOGIN_REQUIRED:WECHAT_MP_PROFILE_DIR is not configured');
|
|
87
88
|
const chrome = detectChrome();
|
|
88
89
|
this._port = await getFreePort();
|
|
90
|
+
|
|
91
|
+
for (const lockFile of ['SingletonLock', 'SingletonCookie', 'SingletonSocket']) {
|
|
92
|
+
const lockPath = path.join(profileDir, lockFile);
|
|
93
|
+
try { if (existsSync(lockPath)) rmSync(lockPath, { force: true }); } catch {}
|
|
94
|
+
}
|
|
95
|
+
|
|
89
96
|
this._proc = spawn(chrome, [
|
|
90
97
|
`--remote-debugging-port=${this._port}`,
|
|
91
98
|
'--no-sandbox',
|
|
@@ -96,7 +103,7 @@ class CdpSession {
|
|
|
96
103
|
'--user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
|
|
97
104
|
`--user-data-dir=${profileDir}`,
|
|
98
105
|
'--window-size=1280,900',
|
|
99
|
-
|
|
106
|
+
'about:blank',
|
|
100
107
|
], { stdio: 'ignore' });
|
|
101
108
|
|
|
102
109
|
for (let i = 0; i < 50; i += 1) {
|
|
@@ -112,6 +119,8 @@ class CdpSession {
|
|
|
112
119
|
await this.cdp('Page.enable');
|
|
113
120
|
await this.cdp('Network.enable');
|
|
114
121
|
await this.cdp('Runtime.enable');
|
|
122
|
+
await this.injectCookies(profileDir);
|
|
123
|
+
await this.navigate(`${WECHAT_MP_ORIGIN}/cgi-bin/home?t=home/index&lang=zh_CN`);
|
|
115
124
|
}
|
|
116
125
|
|
|
117
126
|
_connectWs(wsUrl) {
|
|
@@ -160,6 +169,42 @@ class CdpSession {
|
|
|
160
169
|
await sleep(1500);
|
|
161
170
|
}
|
|
162
171
|
|
|
172
|
+
async injectCookies(profileDir) {
|
|
173
|
+
const cookiesFile = path.join(profileDir, 'cookies.json');
|
|
174
|
+
if (!existsSync(cookiesFile)) {
|
|
175
|
+
console.error(`[wechat-mp-fetch] cookies.json not found at ${cookiesFile}`);
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
try {
|
|
179
|
+
const rawCookies = JSON.parse(readFileSync(cookiesFile, 'utf8'));
|
|
180
|
+
const cookies = rawCookies.map(({
|
|
181
|
+
name,
|
|
182
|
+
value,
|
|
183
|
+
domain,
|
|
184
|
+
path: cookiePath,
|
|
185
|
+
secure,
|
|
186
|
+
httpOnly,
|
|
187
|
+
sameSite,
|
|
188
|
+
expires,
|
|
189
|
+
priority,
|
|
190
|
+
}) => {
|
|
191
|
+
const cookie = { name, value };
|
|
192
|
+
if (domain !== undefined) cookie.domain = domain;
|
|
193
|
+
if (cookiePath !== undefined) cookie.path = cookiePath;
|
|
194
|
+
if (secure !== undefined) cookie.secure = secure;
|
|
195
|
+
if (httpOnly !== undefined) cookie.httpOnly = httpOnly;
|
|
196
|
+
if (sameSite !== undefined) cookie.sameSite = sameSite;
|
|
197
|
+
if (expires !== undefined && expires !== -1) cookie.expires = expires;
|
|
198
|
+
if (priority !== undefined) cookie.priority = priority;
|
|
199
|
+
return cookie;
|
|
200
|
+
});
|
|
201
|
+
await this.cdp('Network.setCookies', { cookies });
|
|
202
|
+
console.error(`[wechat-mp-fetch] Injected ${cookies.length} cookies from cookies.json`);
|
|
203
|
+
} catch (error) {
|
|
204
|
+
console.error(`[wechat-mp-fetch] Failed to inject cookies: ${error?.message ?? error}`);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
163
208
|
async evalValue(expression) {
|
|
164
209
|
const result = await this.cdp('Runtime.evaluate', {
|
|
165
210
|
expression,
|
|
@@ -191,7 +236,13 @@ async function ensureLoggedIn() {
|
|
|
191
236
|
await cdp.navigate(`${WECHAT_MP_ORIGIN}/cgi-bin/home?t=home/index&lang=zh_CN`);
|
|
192
237
|
href = await cdp.currentUrl();
|
|
193
238
|
}
|
|
194
|
-
|
|
239
|
+
let token = '';
|
|
240
|
+
for (let i = 0; i < 12; i += 1) {
|
|
241
|
+
href = await cdp.currentUrl().catch(() => href);
|
|
242
|
+
token = new URL(String(href)).searchParams.get('token') ?? '';
|
|
243
|
+
if (token) break;
|
|
244
|
+
await sleep(500);
|
|
245
|
+
}
|
|
195
246
|
if (!token) {
|
|
196
247
|
throw new Error('LOGIN_REQUIRED:WeChat MP backend login is required');
|
|
197
248
|
}
|
package/package.json
CHANGED
package/src/browser-login.js
CHANGED
|
@@ -104,6 +104,22 @@ export const PLATFORM_CONFIGS = {
|
|
|
104
104
|
?? null;
|
|
105
105
|
return val !== null && val !== baseline;
|
|
106
106
|
},
|
|
107
|
+
async isPageLoggedIn(session) {
|
|
108
|
+
const result = await session.send('Runtime.evaluate', {
|
|
109
|
+
expression: `(() => {
|
|
110
|
+
const href = location.href;
|
|
111
|
+
const text = document.body?.innerText || '';
|
|
112
|
+
return {
|
|
113
|
+
href,
|
|
114
|
+
hasToken: /[?&]token=\\d+/.test(href),
|
|
115
|
+
loginTimedOut: text.includes('登录超时') || text.includes('重新登录')
|
|
116
|
+
};
|
|
117
|
+
})()`,
|
|
118
|
+
returnByValue: true,
|
|
119
|
+
}, 5000);
|
|
120
|
+
const value = result?.result?.value ?? {};
|
|
121
|
+
return Boolean(value.hasToken) && !value.loginTimedOut;
|
|
122
|
+
},
|
|
107
123
|
},
|
|
108
124
|
};
|
|
109
125
|
|
|
@@ -400,7 +416,12 @@ export class BrowserLoginSession {
|
|
|
400
416
|
|
|
401
417
|
async isLoggedIn(baseline) {
|
|
402
418
|
const result = await this.send('Network.getAllCookies', {});
|
|
403
|
-
|
|
419
|
+
const cookieLoggedIn = this._config.isLoggedIn(result.cookies ?? [], baseline);
|
|
420
|
+
if (!cookieLoggedIn) return false;
|
|
421
|
+
if (typeof this._config.isPageLoggedIn === 'function') {
|
|
422
|
+
return this._config.isPageLoggedIn(this);
|
|
423
|
+
}
|
|
424
|
+
return true;
|
|
404
425
|
}
|
|
405
426
|
|
|
406
427
|
_startPolling(connection, baselineSession) {
|