wechat-to-anything 0.6.8 → 0.6.10

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.
@@ -5,7 +5,9 @@
5
5
  "Bash(find /Users/zxw/AITOOL/wechat-to-anything/examples -name *.mjs ! -path */node_modules/* -exec head -40 {})",
6
6
  "Bash(2)",
7
7
  "Bash(ls -la /Users/zxw/AITOOL/wechat-to-anything/examples/*/package.json)",
8
- "mcp__filesystem__read_text_file"
8
+ "mcp__filesystem__read_text_file",
9
+ "Bash(gh issue:*)",
10
+ "Bash(gh api:*)"
9
11
  ]
10
12
  }
11
13
  }
@@ -8,14 +8,12 @@
8
8
  * - cli://gemini → 内置 Gemini CLI 适配器
9
9
  */
10
10
 
11
- import { execFile, spawn } from "node:child_process";
11
+ import { execFile } from "node:child_process";
12
12
  import { writeFile, readFile, unlink, mkdir } from "node:fs/promises";
13
13
  import { join } from "node:path";
14
14
  import { tmpdir } from "node:os";
15
15
  import { randomBytes } from "node:crypto";
16
-
17
- // Windows 上 npm 全局安装生成 .cmd,execFile/spawn 需要 shell: true 才能找到
18
- const IS_WIN = process.platform === "win32";
16
+ import crossSpawn from "cross-spawn";
19
17
 
20
18
  /**
21
19
  * 统一调用接口 — 根据 URL 自动选择适配器
@@ -40,8 +38,12 @@ export async function checkAgent(url) {
40
38
  const name = url.replace("cli://", "");
41
39
  const cmd = { codex: "codex", gemini: "gemini", claude: "claude", openclaw: "openclaw" }[name] || name;
42
40
  return new Promise((resolve, reject) => {
43
- execFile(cmd, ["--version"], { timeout: 5000, shell: IS_WIN }, (err) => {
44
- if (err) reject(new Error(`${cmd} CLI 未安装(npm install -g ${{
41
+ const child = crossSpawn(cmd, ["--version"], { timeout: 5000 });
42
+ child.on("error", (err) => reject(new Error(`${cmd} CLI 未安装(npm install -g ${{
43
+ codex: "@openai/codex", gemini: "@google/gemini-cli", claude: "@anthropic-ai/claude-code", openclaw: "openclaw"
44
+ }[name] || cmd})`)));
45
+ child.on("close", (code) => {
46
+ if (code !== 0) reject(new Error(`${cmd} CLI 未安装(npm install -g ${{
45
47
  codex: "@openai/codex", gemini: "@google/gemini-cli", claude: "@anthropic-ai/claude-code", openclaw: "openclaw"
46
48
  }[name] || cmd})`));
47
49
  else resolve();
@@ -164,23 +166,26 @@ function runCodex(prompt, imagePaths = []) {
164
166
  for (const img of imagePaths) args.push("-i", img);
165
167
  args.push("--", prompt);
166
168
 
167
- execFile("codex", args, { timeout: 300_000, maxBuffer: 2 * 1024 * 1024, cwd: tmpdir(), shell: IS_WIN },
168
- async (err, stdout, stderr) => {
169
+ const child = crossSpawn("codex", args, { timeout: 300_000, cwd: tmpdir() });
170
+ let stdout = "", stderr = "";
171
+ child.stdout.on("data", (d) => (stdout += d));
172
+ child.stderr.on("data", (d) => (stderr += d));
173
+ child.on("close", async () => {
169
174
  try {
170
175
  const reply = await readFile(outFile, "utf-8").catch(() => "");
171
176
  await unlink(outFile).catch(() => {});
172
177
  if (reply.trim()) resolve(reply.trim());
173
178
  else if (stdout.trim()) resolve(stdout.trim());
174
- else if (err) reject(new Error((stderr || err.message).trim().slice(0, 300)));
175
- else resolve("(empty response)");
179
+ else reject(new Error((stderr || "empty response").trim().slice(0, 300)));
176
180
  } catch (e) { reject(e); }
177
181
  });
182
+ child.on("error", (err) => reject(err));
178
183
  });
179
184
  }
180
185
 
181
186
  function runGemini(prompt) {
182
187
  return new Promise((resolve, reject) => {
183
- const child = spawn("gemini", [], { cwd: tmpdir(), stdio: ["pipe", "pipe", "pipe"], timeout: 300_000, shell: IS_WIN });
188
+ const child = crossSpawn("gemini", [], { cwd: tmpdir(), stdio: ["pipe", "pipe", "pipe"], timeout: 300_000 });
184
189
  let stdout = "", stderr = "";
185
190
  child.stdout.on("data", (d) => (stdout += d));
186
191
  child.stderr.on("data", (d) => (stderr += d));
@@ -197,10 +202,9 @@ function runGemini(prompt) {
197
202
 
198
203
  function runClaude(prompt) {
199
204
  return new Promise((resolve, reject) => {
200
- const child = spawn("claude", ["--print", prompt], {
205
+ const child = crossSpawn("claude", ["--print", prompt], {
201
206
  stdio: ["ignore", "pipe", "pipe"],
202
207
  timeout: 300_000,
203
- shell: IS_WIN,
204
208
  });
205
209
  let stdout = "", stderr = "";
206
210
  child.stdout.on("data", (d) => (stdout += d));
@@ -222,7 +226,6 @@ function runOpenClaw(prompt) {
222
226
  cwd: tmpdir(),
223
227
  stdio: ["ignore", "pipe", "pipe"],
224
228
  timeout: 300_000,
225
- shell: IS_WIN,
226
229
  });
227
230
  let stdout = "", stderr = "";
228
231
  child.stdout.on("data", (d) => (stdout += d));
package/cli/bridge.mjs CHANGED
@@ -30,18 +30,19 @@ export async function start(agents, defaultAgent, { port = 9099 } = {}) {
30
30
  if (!creds) {
31
31
  console.log(pc.yellow("📱 首次使用,请扫码登录微信\n"));
32
32
  try {
33
- creds = await loginWithQR(async (qrUrl) => {
33
+ creds = await loginWithQR(async (qrToken, qrImgUrl) => {
34
34
  try {
35
35
  const qrt = await import("qrcode-terminal");
36
36
  await new Promise((resolve) => {
37
- qrt.default.generate(qrUrl, { small: true }, (qr) => {
37
+ qrt.default.generate(qrToken, { small: true }, (qr) => {
38
38
  console.log(qr);
39
39
  resolve();
40
40
  });
41
41
  });
42
42
  } catch {
43
- console.log(`扫码链接: ${qrUrl}`);
43
+ // qrcode-terminal 不可用时 fallback
44
44
  }
45
+ console.log(pc.dim(` 浏览器扫码备用: ${qrImgUrl}`));
45
46
  });
46
47
  console.log(pc.green("✅ 微信登录成功!"));
47
48
  } catch (err) {
package/cli/weixin.mjs CHANGED
@@ -82,7 +82,7 @@ export async function pollQRStatus(qrcode) {
82
82
  */
83
83
  export async function loginWithQR(onQrCode) {
84
84
  const qr = await getQRCode();
85
- await onQrCode(qr.qrcode_img_content);
85
+ await onQrCode(qr.qrcode, qr.qrcode_img_content);
86
86
 
87
87
  const deadline = Date.now() + 5 * 60_000; // 5 min
88
88
  while (Date.now() < deadline) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wechat-to-anything",
3
- "version": "0.6.8",
3
+ "version": "0.6.10",
4
4
  "description": "一条命令,把微信变成任何 AI Agent 的入口",
5
5
  "type": "module",
6
6
  "bin": {
@@ -33,6 +33,7 @@
33
33
  "node": ">=22"
34
34
  },
35
35
  "dependencies": {
36
+ "cross-spawn": "^7.0.6",
36
37
  "picocolors": "^1.1.0",
37
38
  "qrcode-terminal": "^0.12.0"
38
39
  }