@lightcone-ai/daemon 0.15.18 → 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
- `${WECHAT_MP_ORIGIN}/cgi-bin/home?t=home/index&lang=zh_CN`,
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
- const token = new URL(String(href)).searchParams.get('token') ?? '';
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lightcone-ai/daemon",
3
- "version": "0.15.18",
3
+ "version": "0.15.21",
4
4
  "type": "module",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -90,6 +90,37 @@ export const PLATFORM_CONFIGS = {
90
90
  return val !== null && val !== baseline;
91
91
  },
92
92
  },
93
+ wechat_mp: {
94
+ loginUrl: 'https://mp.weixin.qq.com',
95
+ getSessionValue: (cookies) =>
96
+ cookies.find(c => c.name === 'slave_sid')?.value
97
+ ?? cookies.find(c => c.name === 'data_bizuin')?.value
98
+ ?? cookies.find(c => c.name === 'wxuin')?.value
99
+ ?? null,
100
+ isLoggedIn: (cookies, baseline) => {
101
+ const val = cookies.find(c => c.name === 'slave_sid')?.value
102
+ ?? cookies.find(c => c.name === 'data_bizuin')?.value
103
+ ?? cookies.find(c => c.name === 'wxuin')?.value
104
+ ?? null;
105
+ return val !== null && val !== baseline;
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
+ },
123
+ },
93
124
  };
94
125
 
95
126
  export function profileDir(platform, userId) {
@@ -385,7 +416,12 @@ export class BrowserLoginSession {
385
416
 
386
417
  async isLoggedIn(baseline) {
387
418
  const result = await this.send('Network.getAllCookies', {});
388
- return this._config.isLoggedIn(result.cookies ?? [], baseline);
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;
389
425
  }
390
426
 
391
427
  _startPolling(connection, baselineSession) {