claude-codex-wechat 0.1.56 → 0.1.58

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.
@@ -7,12 +7,22 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
7
7
  // src/mcp/tools/sendMedia.ts
8
8
  import { basename } from "node:path";
9
9
  import { z } from "zod";
10
- var BRIDGE_API_URL = process.env.BRIDGE_API_URL || "http://localhost:8787";
11
- async function sendMedia(kind, filePath, fileName) {
12
- const response = await fetch(`${BRIDGE_API_URL}/api/channel/send-media`, {
10
+
11
+ // src/media/sendClient.ts
12
+ function defaultBridgeApiUrl() {
13
+ return process.env.BRIDGE_API_URL || "http://localhost:8787";
14
+ }
15
+ async function sendMediaToWeChat(input) {
16
+ const baseUrl = input.apiBaseUrl ?? defaultBridgeApiUrl();
17
+ const doFetch = input.fetchImpl ?? fetch;
18
+ const response = await doFetch(`${baseUrl}/api/channel/send-media`, {
13
19
  method: "POST",
14
20
  headers: { "content-type": "application/json" },
15
- body: JSON.stringify({ kind, filePath, fileName })
21
+ body: JSON.stringify({
22
+ kind: input.kind,
23
+ filePath: input.filePath,
24
+ ...input.fileName ? { fileName: input.fileName } : {}
25
+ })
16
26
  });
17
27
  if (!response.ok) {
18
28
  const text = await response.text();
@@ -24,6 +34,11 @@ async function sendMedia(kind, filePath, fileName) {
24
34
  }
25
35
  return "\u53D1\u9001\u6210\u529F";
26
36
  }
37
+
38
+ // src/mcp/tools/sendMedia.ts
39
+ async function sendMedia(kind, filePath, fileName) {
40
+ return await sendMediaToWeChat({ kind, filePath, fileName });
41
+ }
27
42
  function registerSendMediaTools(server2) {
28
43
  server2.registerTool(
29
44
  "send_image",
@@ -93,57 +108,64 @@ function registerSendMediaTools(server2) {
93
108
 
94
109
  // src/mcp/tools/douyinDownload.ts
95
110
  import { execFile } from "node:child_process";
96
- import { existsSync } from "node:fs";
97
- import { resolve, dirname, join, basename as basename2 } from "node:path";
98
- import { homedir } from "node:os";
111
+ import { existsSync as existsSync2 } from "node:fs";
112
+ import { dirname, join as join2, basename as basename2 } from "node:path";
113
+ import { homedir as homedir2 } from "node:os";
99
114
  import { fileURLToPath } from "node:url";
100
115
  import { z as z2 } from "zod";
101
- var BRIDGE_API_URL2 = process.env.BRIDGE_API_URL || "http://localhost:8787";
116
+
117
+ // src/media/scriptLocator.ts
118
+ import { existsSync } from "node:fs";
119
+ import { homedir } from "node:os";
120
+ import { join, resolve } from "node:path";
102
121
  function douyinScriptCandidates(baseDir) {
103
122
  return [
104
- // Source layout: src/mcp/tools -> src/mcp/scripts
123
+ // 源码布局:src/mcp/tools -> src/mcp/scripts
105
124
  join(baseDir, "..", "scripts", "douyin-download.mjs"),
106
- // Bundled layout: dist/mcp/mediaServer.js -> dist/mcp/scripts
125
+ // 打包布局:dist/mcp/mediaServer.js -> dist/mcp/scripts
107
126
  join(baseDir, "scripts", "douyin-download.mjs"),
108
- // Older/alternate dist layout fallback
127
+ // 同级包:dist/server -> dist/mcp/scripts(打包后 cli.js 与 mcp/ 平级)
128
+ join(baseDir, "..", "mcp", "scripts", "douyin-download.mjs"),
129
+ // 深一层:src/providers/codex -> src/mcp/scripts
109
130
  join(baseDir, "..", "..", "mcp", "scripts", "douyin-download.mjs"),
110
- // User skills locations (cross-platform)
131
+ // 用户 skills 目录(跨平台)
111
132
  join(homedir(), ".agents", "skills", "douyin-download", "scripts", "douyin-download.mjs"),
112
133
  join(homedir(), ".claude", "skills", "douyin-download", "scripts", "douyin-download.mjs")
113
134
  ];
114
135
  }
136
+ function locateDouyinScript(input) {
137
+ const exists = input.exists ?? existsSync;
138
+ for (const candidate of douyinScriptCandidates(input.baseDir)) {
139
+ const resolved = resolve(candidate);
140
+ if (exists(resolved)) return resolved;
141
+ }
142
+ return void 0;
143
+ }
144
+
145
+ // src/shared/platform.ts
146
+ var isWindows = process.platform === "win32";
147
+ function nodeExecutable() {
148
+ return process.execPath;
149
+ }
150
+
151
+ // src/mcp/tools/douyinDownload.ts
115
152
  function findDouyinScript() {
116
153
  const here = dirname(fileURLToPath(import.meta.url));
117
- const candidates = douyinScriptCandidates(here);
118
- for (const p of candidates) {
119
- const resolved = resolve(p);
120
- if (existsSync(resolved)) return resolved;
121
- }
122
- throw new Error("douyin-download \u811A\u672C\u672A\u627E\u5230");
154
+ const found = locateDouyinScript({ baseDir: here });
155
+ if (!found) throw new Error("douyin-download \u811A\u672C\u672A\u627E\u5230");
156
+ return found;
123
157
  }
124
158
  function runScript(args) {
125
159
  const script = findDouyinScript();
126
160
  return new Promise((resolve2, reject) => {
127
- execFile("node", [script, ...args], { timeout: 12e4 }, (err, stdout, stderr) => {
161
+ execFile(nodeExecutable(), [script, ...args], { timeout: 12e4 }, (err, stdout, stderr) => {
128
162
  if (err) reject(new Error(stderr || err.message));
129
163
  else resolve2({ stdout, stderr });
130
164
  });
131
165
  });
132
166
  }
133
167
  async function sendToWechat(filePath, kind) {
134
- const fileName = basename2(filePath) || "video.mp4";
135
- const response = await fetch(`${BRIDGE_API_URL2}/api/channel/send-media`, {
136
- method: "POST",
137
- headers: { "content-type": "application/json" },
138
- body: JSON.stringify({ kind, filePath, fileName })
139
- });
140
- if (!response.ok) {
141
- const text = await response.text();
142
- throw new Error(`\u53D1\u9001\u5931\u8D25 (HTTP ${response.status}): ${text}`);
143
- }
144
- const result = await response.json();
145
- if (!result.ok) throw new Error(`\u53D1\u9001\u5931\u8D25: ${result.error ?? "\u672A\u77E5\u9519\u8BEF"}`);
146
- return "\u53D1\u9001\u6210\u529F";
168
+ return await sendMediaToWeChat({ kind, filePath, fileName: basename2(filePath) || "video.mp4" });
147
169
  }
148
170
  function registerDouyinTools(server2) {
149
171
  server2.registerTool(
@@ -160,11 +182,11 @@ function registerDouyinTools(server2) {
160
182
  try {
161
183
  const args = [url];
162
184
  if (outputDir) args.push("--output", outputDir);
163
- else args.push("--output", join(homedir(), "Downloads"));
185
+ else args.push("--output", join2(homedir2(), "Downloads"));
164
186
  const { stdout } = await runScript(args);
165
187
  const pathMatch = stdout.match(/(?:已保存|保存到|saved to|文件路径)[::]\s*(.+?\.mp4)/i) || stdout.match(/(\/[^\s]+\.mp4)/);
166
188
  const filePath = pathMatch?.[1]?.trim();
167
- if (!filePath || !existsSync(filePath)) {
189
+ if (!filePath || !existsSync2(filePath)) {
168
190
  return { content: [{ type: "text", text: `\u4E0B\u8F7D\u5B8C\u6210\u4F46\u672A\u627E\u5230\u6587\u4EF6\u8DEF\u5F84\u3002\u811A\u672C\u8F93\u51FA:
169
191
  ${stdout}` }] };
170
192
  }
@@ -186,6 +208,28 @@ ${stdout}` }] };
186
208
  );
187
209
  }
188
210
 
211
+ // src/media/behavior.ts
212
+ var BRIDGE_RULES = {
213
+ sendMeansWeChat: '\u7528\u6237\u8BF4\u7684"\u53D1\u7ED9\u6211""\u53D1\u5230\u5FAE\u4FE1""\u53D1\u51FA\u6765""\u4F20\u7ED9\u6211"\uFF0C\u90FD\u662F\u6307\u628A\u6587\u4EF6\u53D1\u9001\u5230\u4ED6\u7684\u5FAE\u4FE1\u3002',
214
+ douyinNoAsking: '\u770B\u5230\u6296\u97F3\u94FE\u63A5\u5C31\u7ACB\u5373\u4E0B\u8F7D\u5E76\u53D1\u9001\uFF0C\u4E0D\u8981\u53CD\u95EE\u7528\u6237"\u8981\u4E0B\u8F7D\u8FD8\u662F\u8981\u603B\u7ED3"\u2014\u2014\u4E0B\u8F7D\u5E76\u53D1\u9001\u5C31\u662F\u9ED8\u8BA4\u9884\u671F\u3002',
215
+ ignoreThumbnail: "\u5206\u4EAB\u6D88\u606F\u5E38\u9644\u5E26\u5361\u7247\u7F29\u7565\u56FE\uFF0C\u52A0\u8F7D\u5931\u8D25\u65E0\u5173\u7D27\u8981\uFF0C\u76F4\u63A5\u5FFD\u7565\uFF0C\u4E0D\u8981\u56E0\u6B64\u6539\u804A\u56FE\u7247\u3002",
216
+ retryOnce: '\u4E0B\u8F7D\u5931\u8D25\u5148\u539F\u6837\u91CD\u8BD5\u4E00\u6B21\uFF1B\u4ECD\u5931\u8D25\u5C31\u4E00\u53E5\u8BDD\u544A\u8BC9\u7528\u6237"\u6296\u97F3\u4E0B\u8F7D\u5931\u8D25\uFF1A<\u539F\u56E0>"\uFF0C\u4E0D\u8981\u5C94\u5F00\u8BDD\u9898\u3002',
217
+ briefConfirm: '\u6267\u884C\u5B8C\u6210\u540E\u7B80\u77ED\u786E\u8BA4\uFF08\u5982"\u5DF2\u53D1\u9001"\uFF09\uFF0C\u4E0D\u9700\u8981\u5197\u957F\u89E3\u91CA\u3002',
218
+ noInteractiveUI: "\u6CA1\u6709\u4EA4\u4E92\u5F0F\u5F39\u7A97\u6216\u6309\u94AE\uFF1B\u9700\u8981\u7528\u6237\u505A\u9009\u62E9\u65F6\u7528\u5E8F\u53F7\u5217\u8868\u3002"
219
+ };
220
+ function renderMcpInstructions() {
221
+ return [
222
+ "\u4F60\u6B63\u8FD0\u884C\u5728\u4E00\u4E2A\u5FAE\u4FE1\u6865\u63A5\u73AF\u5883\u4E2D\uFF0C\u7528\u6237\u901A\u8FC7\u5FAE\u4FE1\u4E0E\u4F60\u5BF9\u8BDD\u3002",
223
+ BRIDGE_RULES.sendMeansWeChat,
224
+ "",
225
+ "\u5173\u952E\u884C\u4E3A\uFF1A",
226
+ `- ${BRIDGE_RULES.douyinNoAsking}\u7ACB\u5373\u8C03\u7528 download_douyin \u4E0B\u8F7D\u5E76\u53D1\u9001\u3002${BRIDGE_RULES.ignoreThumbnail}${BRIDGE_RULES.retryOnce}`,
227
+ '- \u7528\u6237\u8BF4"\u628AXX\u53D1\u7ED9\u6211"\u65F6\uFF0C\u6839\u636E\u6587\u4EF6\u7C7B\u578B\u8C03\u7528 send_image/send_video/send_file\u3002',
228
+ '- \u751F\u6210\u4E86\u6587\u4EF6\u540E\u7528\u6237\u8BF4"\u53D1\u7ED9\u6211"\uFF0C\u76F4\u63A5\u8C03\u7528\u5BF9\u5E94\u5DE5\u5177\u53D1\u9001\u3002',
229
+ `- ${BRIDGE_RULES.briefConfirm}`
230
+ ].join("\n");
231
+ }
232
+
189
233
  // src/mcp/mediaServer.ts
190
234
  var server = new McpServer(
191
235
  {
@@ -193,16 +237,7 @@ var server = new McpServer(
193
237
  version: "1.0.0"
194
238
  },
195
239
  {
196
- instructions: [
197
- "\u4F60\u6B63\u8FD0\u884C\u5728\u4E00\u4E2A\u5FAE\u4FE1\u6865\u63A5\u73AF\u5883\u4E2D\uFF0C\u7528\u6237\u901A\u8FC7\u5FAE\u4FE1\u4E0E\u4F60\u5BF9\u8BDD\u3002",
198
- '\u7528\u6237\u8BF4\u7684"\u53D1\u7ED9\u6211""\u53D1\u5230\u5FAE\u4FE1""\u53D1\u51FA\u6765""\u4F20\u7ED9\u6211"\u90FD\u662F\u6307\u901A\u8FC7\u672C\u670D\u52A1\u5668\u7684\u5DE5\u5177\u53D1\u9001\u6587\u4EF6\u5230\u7528\u6237\u5FAE\u4FE1\u3002',
199
- "",
200
- "\u5173\u952E\u884C\u4E3A\uFF1A",
201
- '- \u5F53\u7528\u6237\u53D1\u6765\u6296\u97F3\u94FE\u63A5\u6216\u5206\u4EAB\u6587\u6848\u65F6\uFF0C\u7ACB\u5373\u8C03\u7528 download_douyin \u4E0B\u8F7D\u5E76\u53D1\u9001\uFF0C\u65E0\u9700\u8BE2\u95EE\uFF1B\u5206\u4EAB\u81EA\u5E26\u7684\u7F29\u7565\u56FE\u9644\u4EF6\u5373\u4F7F\u5931\u8D25\u4E5F\u5FFD\u7565\uFF0C\u4E0D\u8981\u5C94\u5F00\u53BB\u804A\u56FE\u7247\u3002download_douyin \u5931\u8D25\u65F6\u5148\u91CD\u8BD5\u4E00\u6B21\uFF0C\u4ECD\u5931\u8D25\u5C31\u4E00\u53E5\u8BDD\u544A\u77E5\u7528\u6237"\u6296\u97F3\u4E0B\u8F7D\u5931\u8D25\uFF1A<\u539F\u56E0>"\u3002',
202
- '- \u5F53\u7528\u6237\u8BF4"\u628AXX\u53D1\u7ED9\u6211"\u65F6\uFF0C\u6839\u636E\u6587\u4EF6\u7C7B\u578B\u8C03\u7528 send_image/send_video/send_file\u3002',
203
- '- \u751F\u6210\u4E86\u6587\u4EF6\u540E\u7528\u6237\u8BF4"\u53D1\u7ED9\u6211"\uFF0C\u76F4\u63A5\u8C03\u7528\u5BF9\u5E94\u5DE5\u5177\u53D1\u9001\u3002',
204
- "- \u5B8C\u6210\u540E\u7B80\u77ED\u786E\u8BA4\u5373\u53EF\uFF0C\u4E0D\u9700\u8981\u5197\u957F\u89E3\u91CA\u3002"
205
- ].join("\n")
240
+ instructions: renderMcpInstructions()
206
241
  }
207
242
  );
208
243
  registerSendMediaTools(server);