@opentiny/webmcp-cli 0.0.1-alpha.3 → 0.0.1-alpha.4
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/dist/bin.cjs +113 -146
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +113 -152
- package/dist/bin.js.map +1 -1
- package/dist/index.cjs +71 -139
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +71 -146
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
3
|
-
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
4
|
-
}) : x)(function(x) {
|
|
5
|
-
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
6
|
-
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
7
|
-
});
|
|
8
2
|
|
|
9
3
|
// src/bin.ts
|
|
10
4
|
import { Command } from "commander";
|
|
11
5
|
import pc2 from "picocolors";
|
|
6
|
+
import { readFileSync } from "fs";
|
|
7
|
+
import { resolve } from "path";
|
|
12
8
|
|
|
13
9
|
// src/browser.ts
|
|
14
10
|
import puppeteer from "puppeteer-core";
|
|
@@ -16,20 +12,34 @@ import pc from "picocolors";
|
|
|
16
12
|
import fs from "fs";
|
|
17
13
|
import os from "os";
|
|
18
14
|
import path from "path";
|
|
15
|
+
import http from "http";
|
|
19
16
|
import { spawn } from "child_process";
|
|
20
17
|
import { fileURLToPath } from "url";
|
|
21
18
|
var __filename = fileURLToPath(import.meta.url);
|
|
22
19
|
var __dirname = path.dirname(__filename);
|
|
23
20
|
var CDP_PORT = 9222;
|
|
24
21
|
var CDP_URL = `http://localhost:${CDP_PORT}`;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
22
|
+
function httpGet(url, timeoutMs = 1500) {
|
|
23
|
+
return new Promise((resolve2, reject) => {
|
|
24
|
+
const req = http.get(url, { timeout: timeoutMs }, (res) => {
|
|
25
|
+
let data = "";
|
|
26
|
+
res.on("data", (chunk) => {
|
|
27
|
+
data += chunk.toString();
|
|
28
|
+
});
|
|
29
|
+
res.on("end", () => {
|
|
30
|
+
if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {
|
|
31
|
+
resolve2(data);
|
|
32
|
+
} else {
|
|
33
|
+
reject(new Error(`HTTP ${res.statusCode}`));
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
req.on("error", reject);
|
|
38
|
+
req.on("timeout", () => {
|
|
39
|
+
req.destroy();
|
|
40
|
+
reject(new Error("request timeout"));
|
|
41
|
+
});
|
|
42
|
+
});
|
|
33
43
|
}
|
|
34
44
|
function promiseWithTimeout(promise, timeoutMs = 5e3, errorMsg = "Operation timed out") {
|
|
35
45
|
let timeoutId;
|
|
@@ -45,8 +55,8 @@ function promiseWithTimeout(promise, timeoutMs = 5e3, errorMsg = "Operation time
|
|
|
45
55
|
async function checkCdpReady(url, retries = 3) {
|
|
46
56
|
for (let i = 0; i < retries; i++) {
|
|
47
57
|
try {
|
|
48
|
-
|
|
49
|
-
|
|
58
|
+
await httpGet(url, 1500);
|
|
59
|
+
return true;
|
|
50
60
|
} catch {
|
|
51
61
|
}
|
|
52
62
|
if (i < retries - 1) {
|
|
@@ -55,45 +65,6 @@ async function checkCdpReady(url, retries = 3) {
|
|
|
55
65
|
}
|
|
56
66
|
return false;
|
|
57
67
|
}
|
|
58
|
-
async function killProcessOnPortIfZombie(port) {
|
|
59
|
-
const isResponding = await checkCdpReady(`http://127.0.0.1:${port}/json/version`, 1);
|
|
60
|
-
if (isResponding) {
|
|
61
|
-
console.log(pc.green(`connectBrowser: \u7AEF\u53E3 ${port} \u4E0A\u7684\u6D4F\u89C8\u5668\u5B9E\u4F8B\u4ECD\u5728\u6B63\u5E38\u54CD\u5E94\uFF0C\u8DF3\u8FC7\u5F3A\u6740\uFF0C\u5C1D\u8BD5\u76F4\u63A5\u63A5\u7BA1\u3002`));
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
try {
|
|
65
|
-
const platform = os.platform();
|
|
66
|
-
const { execSync } = __require("child_process");
|
|
67
|
-
if (platform === "darwin" || platform === "linux") {
|
|
68
|
-
console.log(pc.yellow(`\u6B63\u5728\u68C0\u6D4B\u5E76\u6E05\u7406\u5360\u7528 ${port} \u7AEF\u53E3\u7684\u6B8B\u7559\u50F5\u5C38\u8FDB\u7A0B...`));
|
|
69
|
-
const pids = execSync(`lsof -t -i :${port}`).toString().trim();
|
|
70
|
-
if (pids) {
|
|
71
|
-
console.log(pc.yellow(`\u53D1\u73B0\u50F5\u5C38 PID: ${pids.split("\n").join(", ")}\uFF0C\u6B63\u5728\u5F3A\u5236\u7EC8\u6B62...`));
|
|
72
|
-
execSync(`kill -9 ${pids.split("\n").join(" ")}`);
|
|
73
|
-
console.log(pc.green(`\u6210\u529F\u6E05\u7406\u6B8B\u7559\u50F5\u5C38\u8FDB\u7A0B`));
|
|
74
|
-
}
|
|
75
|
-
} else if (platform === "win32") {
|
|
76
|
-
console.log(pc.yellow(`\u6B63\u5728\u68C0\u6D4B\u5E76\u6E05\u7406 Windows \u4E0A\u5360\u7528 ${port} \u7AEF\u53E3\u7684\u6B8B\u7559\u50F5\u5C38\u8FDB\u7A0B...`));
|
|
77
|
-
const output = execSync(`netstat -ano | findstr :${port}`).toString().trim();
|
|
78
|
-
if (output) {
|
|
79
|
-
const lines = output.split("\n");
|
|
80
|
-
const pids = /* @__PURE__ */ new Set();
|
|
81
|
-
lines.forEach((line) => {
|
|
82
|
-
const parts = line.trim().split(/\s+/);
|
|
83
|
-
const pid = parts[parts.length - 1];
|
|
84
|
-
if (pid && /^\d+$/.test(pid) && pid !== "0") {
|
|
85
|
-
pids.add(pid);
|
|
86
|
-
}
|
|
87
|
-
});
|
|
88
|
-
pids.forEach((pid) => {
|
|
89
|
-
console.log(pc.yellow(`\u53D1\u73B0 Windows \u6B8B\u7559\u50F5\u5C38 PID: ${pid}\uFF0C\u6B63\u5728\u5F3A\u5236\u7EC8\u6B62...`));
|
|
90
|
-
execSync(`taskkill /F /PID ${pid}`);
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
} catch (e) {
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
68
|
function getDefaultBrowserPath() {
|
|
98
69
|
const platform = os.platform();
|
|
99
70
|
if (platform === "darwin") {
|
|
@@ -156,20 +127,18 @@ async function startBrowserInBackground() {
|
|
|
156
127
|
child.unref();
|
|
157
128
|
for (let i = 0; i < 20; i++) {
|
|
158
129
|
try {
|
|
159
|
-
const urls = [`http://
|
|
130
|
+
const urls = [`http://127.0.0.1:${CDP_PORT}/json/version`, `http://localhost:${CDP_PORT}/json/version`];
|
|
160
131
|
for (const url of urls) {
|
|
161
132
|
try {
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
return;
|
|
166
|
-
}
|
|
133
|
+
await httpGet(url, 1e3);
|
|
134
|
+
console.log(pc.green(`${browserInfo.name} \u542F\u52A8\u5E76\u5C31\u7EEA\u3002`));
|
|
135
|
+
return;
|
|
167
136
|
} catch (err) {
|
|
168
137
|
}
|
|
169
138
|
}
|
|
170
139
|
} catch (e) {
|
|
171
140
|
}
|
|
172
|
-
await new Promise((
|
|
141
|
+
await new Promise((resolve2) => setTimeout(resolve2, 500));
|
|
173
142
|
}
|
|
174
143
|
throw new Error(`${browserInfo.name} \u542F\u52A8\u8D85\u65F6\uFF0C\u65E0\u6CD5\u8FDE\u63A5\u5230 CDP \u7AEF\u53E3\u3002`);
|
|
175
144
|
}
|
|
@@ -190,90 +159,51 @@ async function connectBrowser() {
|
|
|
190
159
|
return false;
|
|
191
160
|
}
|
|
192
161
|
};
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
162
|
+
const portAddresses = [
|
|
163
|
+
`http://127.0.0.1:${CDP_PORT}/json/version`,
|
|
164
|
+
`http://localhost:${CDP_PORT}/json/version`
|
|
165
|
+
];
|
|
166
|
+
for (const addr of portAddresses) {
|
|
167
|
+
const isReady = await checkCdpReady(addr, 2);
|
|
168
|
+
if (!isReady) continue;
|
|
169
|
+
const browserURL = addr.replace("/json/version", "");
|
|
170
|
+
try {
|
|
171
|
+
console.log(pc.yellow(`connectBrowser: \u68C0\u6D4B\u5230\u7AEF\u53E3 ${CDP_PORT} \u5DF2\u5C31\u7EEA\uFF0C\u6B63\u5728\u8FDE\u63A5 ${browserURL}...`));
|
|
172
|
+
const browser2 = await promiseWithTimeout(
|
|
173
|
+
puppeteer.connect({ browserURL, defaultViewport: null, targetFilter }),
|
|
174
|
+
1e4,
|
|
175
|
+
`puppeteer.connect to ${browserURL} timed out`
|
|
176
|
+
);
|
|
177
|
+
console.log(pc.green(`connectBrowser: \u6210\u529F\u8FDE\u63A5 ${browserURL}`));
|
|
178
|
+
return browser2;
|
|
179
|
+
} catch {
|
|
197
180
|
}
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
181
|
+
}
|
|
182
|
+
console.log(pc.yellow(`connectBrowser: \u7AEF\u53E3 ${CDP_PORT} \u65E0\u54CD\u5E94\uFF0C\u6B63\u5728\u542F\u52A8\u65B0\u7684\u6D4F\u89C8\u5668\u5B9E\u4F8B...`));
|
|
183
|
+
try {
|
|
184
|
+
await startBrowserInBackground();
|
|
185
|
+
} catch (launchError) {
|
|
186
|
+
const msg = launchError instanceof Error ? launchError.message : String(launchError);
|
|
187
|
+
console.error(pc.red(`\u65E0\u6CD5\u542F\u52A8\u6D4F\u89C8\u5668: ${msg}`));
|
|
188
|
+
throw new Error("Browser launch failed.");
|
|
189
|
+
}
|
|
190
|
+
for (const addr of portAddresses) {
|
|
191
|
+
const isReady = await checkCdpReady(addr, 3);
|
|
192
|
+
if (!isReady) continue;
|
|
193
|
+
const browserURL = addr.replace("/json/version", "");
|
|
211
194
|
try {
|
|
212
|
-
|
|
213
|
-
if (!isLocalhostReady) {
|
|
214
|
-
throw new Error("localhost CDP port not responding");
|
|
215
|
-
}
|
|
216
|
-
console.log(pc.yellow("connectBrowser: \u6B63\u5728\u5C1D\u8BD5\u8FDE\u63A5 localhost:9222..."));
|
|
195
|
+
console.log(pc.yellow(`connectBrowser: \u6D4F\u89C8\u5668\u5DF2\u542F\u52A8\uFF0C\u6B63\u5728\u8FDE\u63A5 ${browserURL}...`));
|
|
217
196
|
const browser2 = await promiseWithTimeout(
|
|
218
|
-
puppeteer.connect({
|
|
219
|
-
browserURL: `http://localhost:${CDP_PORT}`,
|
|
220
|
-
defaultViewport: null,
|
|
221
|
-
targetFilter
|
|
222
|
-
}),
|
|
197
|
+
puppeteer.connect({ browserURL, defaultViewport: null, targetFilter }),
|
|
223
198
|
1e4,
|
|
224
|
-
|
|
199
|
+
`puppeteer.connect to ${browserURL} after launch timed out`
|
|
225
200
|
);
|
|
226
|
-
console.log(pc.green(
|
|
201
|
+
console.log(pc.green(`connectBrowser: \u6210\u529F\u8FDE\u63A5 ${browserURL}`));
|
|
227
202
|
return browser2;
|
|
228
|
-
} catch
|
|
229
|
-
console.log(pc.yellow(`connectBrowser: \u8FDE\u63A5\u5931\u8D25\uFF0C\u5C06\u5C1D\u8BD5\u5524\u8D77\u6D4F\u89C8\u5668\u3002\u9519\u8BEF\u539F\u56E0: ${error2 instanceof Error ? error2.message : String(error2)}`));
|
|
230
|
-
try {
|
|
231
|
-
await killProcessOnPortIfZombie(CDP_PORT);
|
|
232
|
-
await startBrowserInBackground();
|
|
233
|
-
try {
|
|
234
|
-
const is127Ready = await checkCdpReady(`http://127.0.0.1:${CDP_PORT}/json/version`, 3);
|
|
235
|
-
if (!is127Ready) {
|
|
236
|
-
throw new Error("127.0.0.1 CDP port not responding after launch");
|
|
237
|
-
}
|
|
238
|
-
console.log(pc.yellow("connectBrowser: \u6D4F\u89C8\u5668\u5DF2\u542F\u52A8\uFF0C\u6B63\u5728\u5C1D\u8BD5\u8FDE\u63A5 127.0.0.1:9222..."));
|
|
239
|
-
const browser2 = await promiseWithTimeout(
|
|
240
|
-
puppeteer.connect({
|
|
241
|
-
browserURL: `http://127.0.0.1:${CDP_PORT}`,
|
|
242
|
-
defaultViewport: null,
|
|
243
|
-
targetFilter
|
|
244
|
-
}),
|
|
245
|
-
1e4,
|
|
246
|
-
"puppeteer.connect to 127.0.0.1 after launch timed out"
|
|
247
|
-
);
|
|
248
|
-
console.log(pc.green("connectBrowser: \u6210\u529F\u8FDE\u63A5 127.0.0.1:9222"));
|
|
249
|
-
return browser2;
|
|
250
|
-
} catch (e) {
|
|
251
|
-
const isLocalhostReady = await checkCdpReady(`http://localhost:${CDP_PORT}/json/version`, 3);
|
|
252
|
-
if (!isLocalhostReady) {
|
|
253
|
-
throw new Error("localhost CDP port not responding after launch");
|
|
254
|
-
}
|
|
255
|
-
console.log(pc.yellow("connectBrowser: \u6B63\u5728\u5C1D\u8BD5\u8FDE\u63A5 localhost:9222..."));
|
|
256
|
-
const browser2 = await promiseWithTimeout(
|
|
257
|
-
puppeteer.connect({
|
|
258
|
-
browserURL: `http://localhost:${CDP_PORT}`,
|
|
259
|
-
defaultViewport: null,
|
|
260
|
-
targetFilter
|
|
261
|
-
}),
|
|
262
|
-
1e4,
|
|
263
|
-
"puppeteer.connect to localhost after launch timed out"
|
|
264
|
-
);
|
|
265
|
-
console.log(pc.green("connectBrowser: \u6210\u529F\u8FDE\u63A5 localhost:9222"));
|
|
266
|
-
return browser2;
|
|
267
|
-
}
|
|
268
|
-
} catch (launchError) {
|
|
269
|
-
const msg = launchError instanceof Error ? launchError.message : String(launchError);
|
|
270
|
-
console.error(pc.red(`\u65E0\u6CD5\u8FDE\u63A5\u6216\u542F\u52A8\u6D4F\u89C8\u5668: ${msg}`));
|
|
271
|
-
console.error(pc.yellow(`\u{1F4A1} \u63D0\u793A\uFF1A\u7531\u4E8E\u6211\u4EEC\u8981\u4F7F\u7528\u4F60\u65E5\u5E38\u7684\u9ED8\u8BA4\u6D4F\u89C8\u5668\uFF08\u5305\u542B\u4F60\u7684\u4E66\u7B7E\u548C\u767B\u5F55\u6001\uFF09\uFF0C\u5982\u679C\u4F60\u7684 Chrome/Edge \u76EE\u524D\u6B63\u5904\u4E8E\u6253\u5F00\u72B6\u6001\uFF0C\u5B83\u4F1A\u62D2\u7EDD\u4F7F\u7528\u5E26\u6709\u8C03\u8BD5\u7AEF\u53E3\u7684\u65B0\u53C2\u6570\u542F\u52A8\u3002`));
|
|
272
|
-
console.error(pc.yellow(`\u{1F449} \u89E3\u51B3\u529E\u6CD5\uFF1A\u8BF7\u5148\u5B8C\u5168\u9000\u51FA\u5F53\u524D\u7684 Chrome \u6216 Edge \u6D4F\u89C8\u5668\uFF08\u5728 Mac \u4E0A\u6309 Cmd+Q\uFF0CWindows \u4E0A\u53F3\u952E\u4EFB\u52A1\u680F\u56FE\u6807\u9000\u51FA\uFF09\uFF0C\u7136\u540E\u518D\u91CD\u65B0\u8FD0\u884C\u547D\u4EE4\u3002`));
|
|
273
|
-
throw new Error("Browser connection failed.");
|
|
274
|
-
}
|
|
203
|
+
} catch {
|
|
275
204
|
}
|
|
276
205
|
}
|
|
206
|
+
throw new Error(`\u65E0\u6CD5\u8FDE\u63A5\u5230\u6D4F\u89C8\u5668\uFF08\u7AEF\u53E3 ${CDP_PORT}\uFF09\uFF0C\u8BF7\u68C0\u67E5 Chrome/Edge \u662F\u5426\u5DF2\u5B89\u88C5\u3002`);
|
|
277
207
|
}
|
|
278
208
|
async function getPageTargetId(page2) {
|
|
279
209
|
const session = await page2.target().createCDPSession();
|
|
@@ -351,14 +281,12 @@ async function getTargetPage(browser2, tabid2) {
|
|
|
351
281
|
let activeTargetId = null;
|
|
352
282
|
for (const url of urls) {
|
|
353
283
|
try {
|
|
354
|
-
const
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
break;
|
|
361
|
-
}
|
|
284
|
+
const body = await httpGet(url, 1e3);
|
|
285
|
+
const targetsData = JSON.parse(body);
|
|
286
|
+
const active = targetsData.find((t) => t.type === "page" && !t.url.startsWith("devtools://"));
|
|
287
|
+
if (active) {
|
|
288
|
+
activeTargetId = active.id;
|
|
289
|
+
break;
|
|
362
290
|
}
|
|
363
291
|
} catch {
|
|
364
292
|
}
|
|
@@ -404,7 +332,7 @@ async function injectWebMCPPolyfillAndTools(page2, force = false) {
|
|
|
404
332
|
const msg = err instanceof Error ? err.message : String(err);
|
|
405
333
|
throw new Error("\u81EA\u52A8\u6CE8\u5165\u811A\u672C\u6267\u884C\u5931\u8D25: " + msg);
|
|
406
334
|
}
|
|
407
|
-
await new Promise((
|
|
335
|
+
await new Promise((resolve2) => setTimeout(resolve2, 300));
|
|
408
336
|
}
|
|
409
337
|
await injectDomainTools(page2);
|
|
410
338
|
}
|
|
@@ -492,7 +420,7 @@ async function stateCommand({ tabid: tabid2 }) {
|
|
|
492
420
|
if (pUrl.startsWith("devtools://")) return null;
|
|
493
421
|
const pTitle = await Promise.race([
|
|
494
422
|
p.title().catch(() => "Unknown"),
|
|
495
|
-
new Promise((
|
|
423
|
+
new Promise((resolve2) => setTimeout(() => resolve2("Unknown"), 500))
|
|
496
424
|
]);
|
|
497
425
|
return {
|
|
498
426
|
// 使用真实的 Chrome target ID,而非数组下标
|
|
@@ -598,7 +526,7 @@ async function tabsOpenCommand(url) {
|
|
|
598
526
|
url = normalizeUrl(url);
|
|
599
527
|
await page2.goto(url, { waitUntil: "domcontentloaded" });
|
|
600
528
|
await injectIntoPage(page2);
|
|
601
|
-
await new Promise((
|
|
529
|
+
await new Promise((resolve2) => setTimeout(resolve2, 500));
|
|
602
530
|
return {
|
|
603
531
|
success: true,
|
|
604
532
|
tabid: await getPageTargetId(page2),
|
|
@@ -699,7 +627,7 @@ async function tabsForwardCommand(tabid2) {
|
|
|
699
627
|
// package.json
|
|
700
628
|
var package_default = {
|
|
701
629
|
name: "@opentiny/webmcp-cli",
|
|
702
|
-
version: "0.0.1-alpha.
|
|
630
|
+
version: "0.0.1-alpha.4",
|
|
703
631
|
type: "module",
|
|
704
632
|
description: "WebMCP CLI for AI Agents to interact with browser via Puppeteer",
|
|
705
633
|
main: "dist/index.js",
|
|
@@ -761,6 +689,19 @@ function handleCommandError(error, commandName) {
|
|
|
761
689
|
console.error(pc2.red(`Error executing ${commandName} command: ${msg}`));
|
|
762
690
|
process.exit(1);
|
|
763
691
|
}
|
|
692
|
+
function expandFileRefs(argsJson) {
|
|
693
|
+
return argsJson.replace(/"@(base64)?file:([^"]+)"/g, (_match, base64Flag, filePath) => {
|
|
694
|
+
const absPath = resolve(process.cwd(), filePath);
|
|
695
|
+
let content;
|
|
696
|
+
try {
|
|
697
|
+
content = readFileSync(absPath, "utf-8");
|
|
698
|
+
} catch (e) {
|
|
699
|
+
throw new Error(`\u65E0\u6CD5\u8BFB\u53D6\u6587\u4EF6\u5F15\u7528 "${filePath}": ${e.message}`);
|
|
700
|
+
}
|
|
701
|
+
const value = base64Flag ? Buffer.from(content, "utf-8").toString("base64") : content;
|
|
702
|
+
return JSON.stringify(value);
|
|
703
|
+
});
|
|
704
|
+
}
|
|
764
705
|
program.name("webmcp-cli").description("WebMCP CLI for interacting with browser via CDP").version(package_default.version).option("-w, --workspace <path>", "\u6307\u5B9A\u81EA\u5B9A\u4E49\u7684\u6D4F\u89C8\u5668\u5DE5\u4F5C\u7A7A\u95F4\uFF08\u7528\u6237\u914D\u7F6E\u76EE\u5F55\uFF09\u8DEF\u5F84").hook("preAction", (thisCommand) => {
|
|
765
706
|
const opts = thisCommand.opts();
|
|
766
707
|
if (opts.workspace) {
|
|
@@ -775,11 +716,31 @@ program.command("state").description("\u83B7\u53D6\u6D4F\u89C8\u5668\u5F53\u524D
|
|
|
775
716
|
handleCommandError(error, "state");
|
|
776
717
|
}
|
|
777
718
|
});
|
|
778
|
-
program.command("run <toolName>
|
|
719
|
+
program.command("run <toolName> [argsJson]").description("\u5411\u6307\u5B9A\u9875\u7B7E\u8C03\u7528\u6307\u5B9A\u7684 WebMCP \u5DE5\u5177\u6267\u884C\u64CD\u4F5C").option("-t, --tabid <id>", "\u6307\u5B9A\u9875\u7B7E\u7684 ID").option(
|
|
720
|
+
"-f, --file <path>",
|
|
721
|
+
`\u4ECE\u6307\u5B9A .json \u6587\u4EF6\u8BFB\u53D6\u6574\u4E2A argsJson\uFF08\u6587\u4EF6\u5185\u5BB9\u5373\u4E3A\u53C2\u6570 JSON\uFF09\u3002
|
|
722
|
+
\u5982\u9700\u5728 argsJson \u4E2D\u5185\u8054\u5F15\u7528\u6587\u4EF6\uFF0C\u4F7F\u7528\u5360\u4F4D\u7B26\u8BED\u6CD5\uFF1A
|
|
723
|
+
@file:<path> \u8BFB\u53D6\u6587\u4EF6\u539F\u59CB\u6587\u672C
|
|
724
|
+
@base64file:<path> \u8BFB\u53D6\u6587\u4EF6\u5E76 Base64 \u7F16\u7801
|
|
725
|
+
\u793A\u4F8B\uFF1Awebmcp-cli run mytool '{"content":"@base64file:./doc.md"}'`
|
|
726
|
+
).action(async (toolName, argsJson, options) => {
|
|
779
727
|
try {
|
|
728
|
+
let finalArgsJson = argsJson;
|
|
729
|
+
if (options.file) {
|
|
730
|
+
const filePath = resolve(process.cwd(), options.file);
|
|
731
|
+
try {
|
|
732
|
+
finalArgsJson = readFileSync(filePath, "utf-8").trim();
|
|
733
|
+
} catch (e) {
|
|
734
|
+
throw new Error(`\u65E0\u6CD5\u8BFB\u53D6\u6587\u4EF6 "${filePath}": ${e.message}`);
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
if (!finalArgsJson) {
|
|
738
|
+
throw new Error("\u5FC5\u987B\u63D0\u4F9B argsJson \u53C2\u6570\u6216\u901A\u8FC7 -f/--file \u6307\u5B9A\u53C2\u6570\u6587\u4EF6");
|
|
739
|
+
}
|
|
740
|
+
finalArgsJson = expandFileRefs(finalArgsJson);
|
|
780
741
|
const result2 = await runCommand({
|
|
781
742
|
toolName,
|
|
782
|
-
argsJson,
|
|
743
|
+
argsJson: finalArgsJson,
|
|
783
744
|
tabid: parseTabId(options.tabid)
|
|
784
745
|
});
|
|
785
746
|
console.log(JSON.stringify(result2, null, 2));
|