wechat-to-anything 0.6.7 → 0.6.9
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.
- package/.claude/settings.local.json +3 -1
- package/cli/agent-adapter.mjs +17 -9
- package/cli/bridge.mjs +3 -4
- package/cli/cdn.mjs +2 -2
- package/package.json +2 -1
|
@@ -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
|
}
|
package/cli/agent-adapter.mjs
CHANGED
|
@@ -8,11 +8,12 @@
|
|
|
8
8
|
* - cli://gemini → 内置 Gemini CLI 适配器
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import { execFile
|
|
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
|
+
import crossSpawn from "cross-spawn";
|
|
16
17
|
|
|
17
18
|
/**
|
|
18
19
|
* 统一调用接口 — 根据 URL 自动选择适配器
|
|
@@ -37,8 +38,12 @@ export async function checkAgent(url) {
|
|
|
37
38
|
const name = url.replace("cli://", "");
|
|
38
39
|
const cmd = { codex: "codex", gemini: "gemini", claude: "claude", openclaw: "openclaw" }[name] || name;
|
|
39
40
|
return new Promise((resolve, reject) => {
|
|
40
|
-
|
|
41
|
-
|
|
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 ${{
|
|
42
47
|
codex: "@openai/codex", gemini: "@google/gemini-cli", claude: "@anthropic-ai/claude-code", openclaw: "openclaw"
|
|
43
48
|
}[name] || cmd})`));
|
|
44
49
|
else resolve();
|
|
@@ -161,23 +166,26 @@ function runCodex(prompt, imagePaths = []) {
|
|
|
161
166
|
for (const img of imagePaths) args.push("-i", img);
|
|
162
167
|
args.push("--", prompt);
|
|
163
168
|
|
|
164
|
-
|
|
165
|
-
|
|
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 () => {
|
|
166
174
|
try {
|
|
167
175
|
const reply = await readFile(outFile, "utf-8").catch(() => "");
|
|
168
176
|
await unlink(outFile).catch(() => {});
|
|
169
177
|
if (reply.trim()) resolve(reply.trim());
|
|
170
178
|
else if (stdout.trim()) resolve(stdout.trim());
|
|
171
|
-
else
|
|
172
|
-
else resolve("(empty response)");
|
|
179
|
+
else reject(new Error((stderr || "empty response").trim().slice(0, 300)));
|
|
173
180
|
} catch (e) { reject(e); }
|
|
174
181
|
});
|
|
182
|
+
child.on("error", (err) => reject(err));
|
|
175
183
|
});
|
|
176
184
|
}
|
|
177
185
|
|
|
178
186
|
function runGemini(prompt) {
|
|
179
187
|
return new Promise((resolve, reject) => {
|
|
180
|
-
const child =
|
|
188
|
+
const child = crossSpawn("gemini", [], { cwd: tmpdir(), stdio: ["pipe", "pipe", "pipe"], timeout: 300_000 });
|
|
181
189
|
let stdout = "", stderr = "";
|
|
182
190
|
child.stdout.on("data", (d) => (stdout += d));
|
|
183
191
|
child.stderr.on("data", (d) => (stderr += d));
|
|
@@ -194,7 +202,7 @@ function runGemini(prompt) {
|
|
|
194
202
|
|
|
195
203
|
function runClaude(prompt) {
|
|
196
204
|
return new Promise((resolve, reject) => {
|
|
197
|
-
const child =
|
|
205
|
+
const child = crossSpawn("claude", ["--print", prompt], {
|
|
198
206
|
stdio: ["ignore", "pipe", "pipe"],
|
|
199
207
|
timeout: 300_000,
|
|
200
208
|
});
|
package/cli/bridge.mjs
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
loadCredentials, loginWithQR, getUpdates,
|
|
5
5
|
sendMessage, sendImageByUrl, sendVideoByUrl,
|
|
6
6
|
extractText, extractMedia,
|
|
7
|
-
getConfig, sendTyping,
|
|
7
|
+
getConfig, sendTyping, buildHeaders, BASE_URL,
|
|
8
8
|
} from "./weixin.mjs";
|
|
9
9
|
import { downloadAndDecrypt, downloadMediaToFile, uploadToCdn } from "./cdn.mjs";
|
|
10
10
|
import { callAgentAuto, checkAgent } from "./agent-adapter.mjs";
|
|
@@ -130,8 +130,6 @@ export async function start(agents, defaultAgent, { port = 9099 } = {}) {
|
|
|
130
130
|
try {
|
|
131
131
|
const { execFileSync } = await import("node:child_process");
|
|
132
132
|
const { statSync, writeFileSync } = await import("node:fs");
|
|
133
|
-
const { uploadToCdn } = await import("./cdn.mjs");
|
|
134
|
-
const { buildHeaders, BASE_URL: baseUrl } = await import("./weixin.mjs");
|
|
135
133
|
|
|
136
134
|
let audioFile = audioSrc;
|
|
137
135
|
if (audioSrc.startsWith("http://") || audioSrc.startsWith("https://")) {
|
|
@@ -166,7 +164,7 @@ export async function start(agents, defaultAgent, { port = 9099 } = {}) {
|
|
|
166
164
|
},
|
|
167
165
|
base_info: {},
|
|
168
166
|
});
|
|
169
|
-
await fetch(`${
|
|
167
|
+
await fetch(`${BASE_URL}/ilink/bot/sendmessage`, {
|
|
170
168
|
method: "POST", headers: buildHeaders(creds.token, body), body,
|
|
171
169
|
});
|
|
172
170
|
console.log(pc.green(`→ [语音] 已发送 (${durationMs}ms)`));
|
|
@@ -246,6 +244,7 @@ export async function start(agents, defaultAgent, { port = 9099 } = {}) {
|
|
|
246
244
|
if (bodySize > 1_048_576) { // 1MB limit
|
|
247
245
|
res.writeHead(413, { "Content-Type": "application/json" });
|
|
248
246
|
res.end(JSON.stringify({ error: "body too large (max 1MB)" }));
|
|
247
|
+
req.destroy();
|
|
249
248
|
return;
|
|
250
249
|
}
|
|
251
250
|
body += chunk;
|
package/cli/cdn.mjs
CHANGED
|
@@ -80,7 +80,7 @@ export async function downloadMediaToFile(encryptQueryParam, aesKeyBase64, ext =
|
|
|
80
80
|
*/
|
|
81
81
|
export async function uploadImageWithThumb(filePath, toUserId, token) {
|
|
82
82
|
const { buildHeaders, BASE_URL } = await import("./weixin.mjs");
|
|
83
|
-
const { execFileSync } = await import("child_process");
|
|
83
|
+
const { execFileSync } = await import("node:child_process");
|
|
84
84
|
|
|
85
85
|
const plaintext = await readFile(filePath);
|
|
86
86
|
const rawsize = plaintext.length;
|
|
@@ -183,7 +183,7 @@ export async function uploadImageWithThumb(filePath, toUserId, token) {
|
|
|
183
183
|
*/
|
|
184
184
|
export async function uploadVideoWithThumb(filePath, toUserId, token) {
|
|
185
185
|
const { buildHeaders, BASE_URL } = await import("./weixin.mjs");
|
|
186
|
-
const { execFileSync } = await import("child_process");
|
|
186
|
+
const { execFileSync } = await import("node:child_process");
|
|
187
187
|
|
|
188
188
|
const plaintext = await readFile(filePath);
|
|
189
189
|
const rawsize = plaintext.length;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wechat-to-anything",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.9",
|
|
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
|
}
|