@opentiny/webmcp-cli 0.0.1-alpha.4 → 0.0.1-alpha.6
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 +220 -58
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +203 -41
- package/dist/bin.js.map +1 -1
- package/dist/index.cjs +10 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +10 -7
- package/dist/index.js.map +1 -1
- package/dist/webmcp-tools/juejin.cn.js +54 -21
- package/package.json +2 -1
package/dist/bin.cjs
CHANGED
|
@@ -26,25 +26,197 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
26
26
|
// src/bin.ts
|
|
27
27
|
var import_commander = require("commander");
|
|
28
28
|
var import_picocolors2 = __toESM(require("picocolors"), 1);
|
|
29
|
-
var
|
|
30
|
-
var
|
|
29
|
+
var import_fs3 = require("fs");
|
|
30
|
+
var import_path3 = require("path");
|
|
31
|
+
|
|
32
|
+
// src/expand-file-refs.ts
|
|
33
|
+
var import_fs = require("fs");
|
|
34
|
+
var import_path = require("path");
|
|
35
|
+
var import_url = require("url");
|
|
36
|
+
var JSON_STRING_LITERAL = /"(?:[^"\\]|\\.)*"/g;
|
|
37
|
+
var UNQUOTED_FILE_REF = /(?<![\\"])@(base64)?file:([^\s"',}\]]+)/g;
|
|
38
|
+
var FILE_REF_PREFIX = /^@(base64)?file:(.+)$/s;
|
|
39
|
+
function resolveFilePath(filePath, baseDir = process.cwd()) {
|
|
40
|
+
let normalizedPath = filePath.trim();
|
|
41
|
+
if (normalizedPath.startsWith('"') && normalizedPath.endsWith('"') || normalizedPath.startsWith("'") && normalizedPath.endsWith("'")) {
|
|
42
|
+
normalizedPath = normalizedPath.slice(1, -1).trim();
|
|
43
|
+
}
|
|
44
|
+
if (normalizedPath.startsWith("file://")) {
|
|
45
|
+
normalizedPath = (0, import_url.fileURLToPath)(normalizedPath);
|
|
46
|
+
}
|
|
47
|
+
if ((0, import_path.isAbsolute)(normalizedPath)) {
|
|
48
|
+
return (0, import_path.normalize)(normalizedPath);
|
|
49
|
+
}
|
|
50
|
+
return (0, import_path.resolve)(baseDir, normalizedPath);
|
|
51
|
+
}
|
|
52
|
+
function decodeFilePath(rawPath) {
|
|
53
|
+
return rawPath.replace(/\\\\/g, "\\");
|
|
54
|
+
}
|
|
55
|
+
function readFileRefContent(filePath, baseDir, base64) {
|
|
56
|
+
const absPath = resolveFilePath(filePath, baseDir);
|
|
57
|
+
let content;
|
|
58
|
+
try {
|
|
59
|
+
content = (0, import_fs.readFileSync)(absPath, "utf-8");
|
|
60
|
+
} catch (e) {
|
|
61
|
+
throw new Error(`\u65E0\u6CD5\u8BFB\u53D6\u6587\u4EF6\u5F15\u7528 "${filePath}" (${absPath}): ${e.message}`);
|
|
62
|
+
}
|
|
63
|
+
return base64 ? Buffer.from(content, "utf-8").toString("base64") : content;
|
|
64
|
+
}
|
|
65
|
+
function expandFileRefValue(rawInner, baseDir) {
|
|
66
|
+
const match = rawInner.match(FILE_REF_PREFIX);
|
|
67
|
+
if (!match) {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
const [, base64Flag, rawPath] = match;
|
|
71
|
+
const filePath = decodeFilePath(rawPath);
|
|
72
|
+
const value = readFileRefContent(filePath, baseDir, Boolean(base64Flag));
|
|
73
|
+
return JSON.stringify(value);
|
|
74
|
+
}
|
|
75
|
+
function expandQuotedFileRefs(argsJson, baseDir) {
|
|
76
|
+
return argsJson.replace(JSON_STRING_LITERAL, (jsonStringLiteral) => {
|
|
77
|
+
const rawInner = jsonStringLiteral.slice(1, -1);
|
|
78
|
+
const replacement = expandFileRefValue(rawInner, baseDir);
|
|
79
|
+
return replacement ?? jsonStringLiteral;
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
function expandUnquotedFileRefs(argsJson, baseDir) {
|
|
83
|
+
return argsJson.replace(UNQUOTED_FILE_REF, (match, base64Flag, filePath) => {
|
|
84
|
+
const value = readFileRefContent(filePath, baseDir, Boolean(base64Flag));
|
|
85
|
+
return JSON.stringify(value);
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
function expandFileRefs(argsJson, baseDir = process.cwd()) {
|
|
89
|
+
const withQuotedExpanded = expandQuotedFileRefs(argsJson, baseDir);
|
|
90
|
+
return expandUnquotedFileRefs(withQuotedExpanded, baseDir);
|
|
91
|
+
}
|
|
92
|
+
function getFileBaseDir(fileOption) {
|
|
93
|
+
if (!fileOption) {
|
|
94
|
+
return process.cwd();
|
|
95
|
+
}
|
|
96
|
+
return (0, import_path.dirname)((0, import_path.resolve)(process.cwd(), fileOption));
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// src/parse-run-args.ts
|
|
100
|
+
var import_json5 = __toESM(require("json5"), 1);
|
|
101
|
+
function cleanJsonString(str) {
|
|
102
|
+
let cleaned = str.trim();
|
|
103
|
+
if (cleaned.startsWith("'") && cleaned.endsWith("'")) {
|
|
104
|
+
cleaned = cleaned.slice(1, -1).trim();
|
|
105
|
+
}
|
|
106
|
+
return cleaned;
|
|
107
|
+
}
|
|
108
|
+
function looksLikeObjectBody(raw) {
|
|
109
|
+
return /^("?[\w-]+"?\s*:)/.test(raw);
|
|
110
|
+
}
|
|
111
|
+
function joinShellArgs(args) {
|
|
112
|
+
const cleaned = args.map(cleanJsonString);
|
|
113
|
+
const first = cleaned[0] ?? "";
|
|
114
|
+
if (first.startsWith("{")) {
|
|
115
|
+
return cleaned.join(" ");
|
|
116
|
+
}
|
|
117
|
+
if (looksLikeObjectBody(first)) {
|
|
118
|
+
let joined = cleaned.join(" ");
|
|
119
|
+
if (!joined.startsWith("{")) {
|
|
120
|
+
joined = `{${joined}}`;
|
|
121
|
+
}
|
|
122
|
+
if (!joined.endsWith("}")) {
|
|
123
|
+
joined = `${joined}}`;
|
|
124
|
+
}
|
|
125
|
+
return joined;
|
|
126
|
+
}
|
|
127
|
+
return cleaned.join(" ");
|
|
128
|
+
}
|
|
129
|
+
function insertMissingCommas(raw) {
|
|
130
|
+
return raw.replace(/"(\s+)("?[\w-]+"?\s*:)/g, '",$2');
|
|
131
|
+
}
|
|
132
|
+
function quoteUnquotedStringValues(raw) {
|
|
133
|
+
return raw.replace(
|
|
134
|
+
/([{,]\s*(?:"([^"]+)"|([\w-]+))\s*:\s*)(?!"@(?:base64)?file:|"|true|false|null|-?\d|\{|\[)([^",}\]]+?)(?=\s*[,}])/g,
|
|
135
|
+
(_match, prefix, _quotedKey, _unquotedKey, value) => {
|
|
136
|
+
const trimmed = value.trim();
|
|
137
|
+
if (/^-?\d+(\.\d+)?([eE][+-]?\d+)?$/.test(trimmed)) {
|
|
138
|
+
return prefix + trimmed;
|
|
139
|
+
}
|
|
140
|
+
return prefix + JSON.stringify(trimmed);
|
|
141
|
+
}
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
function normalizeShellDamagedJson(raw) {
|
|
145
|
+
let normalized = raw.trim();
|
|
146
|
+
normalized = insertMissingCommas(normalized);
|
|
147
|
+
normalized = quoteUnquotedStringValues(normalized);
|
|
148
|
+
return normalized;
|
|
149
|
+
}
|
|
150
|
+
function buildArgsFromKeyValuePairs(args) {
|
|
151
|
+
const obj = {};
|
|
152
|
+
for (const pair of args) {
|
|
153
|
+
const index = pair.indexOf("=");
|
|
154
|
+
if (index === -1) {
|
|
155
|
+
throw new Error(`\u65E0\u6548\u7684\u53C2\u6570\u683C\u5F0F "${pair}"\u3002\u8BF7\u4F7F\u7528 key=value\uFF0C\u6216 JSON / -f \u6587\u4EF6\u3002`);
|
|
156
|
+
}
|
|
157
|
+
const key = pair.substring(0, index).trim();
|
|
158
|
+
let val = cleanJsonString(pair.substring(index + 1).trim());
|
|
159
|
+
try {
|
|
160
|
+
obj[key] = JSON.parse(val);
|
|
161
|
+
} catch {
|
|
162
|
+
obj[key] = val;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return JSON.stringify(obj);
|
|
166
|
+
}
|
|
167
|
+
function parseArgsJson(raw) {
|
|
168
|
+
const trimmed = cleanJsonString(raw);
|
|
169
|
+
try {
|
|
170
|
+
return JSON.stringify(import_json5.default.parse(trimmed));
|
|
171
|
+
} catch (firstError) {
|
|
172
|
+
const repaired = normalizeShellDamagedJson(trimmed);
|
|
173
|
+
try {
|
|
174
|
+
return JSON.stringify(import_json5.default.parse(repaired));
|
|
175
|
+
} catch {
|
|
176
|
+
const hint = `\u63D0\u793A\uFF1Abash \u4E2D JSON \u5FC5\u987B\u7528\u5355\u5F15\u53F7\u5305\u88F9\uFF0C\u4F8B\u5982 '{"title":"\u6807\u9898","content":"@base64file:./article.md"}'\uFF1B\u6216\u4F7F\u7528 key=value\uFF1Atitle=\u6807\u9898 content=@base64file:./article.md\uFF1B\u6216\u4F7F\u7528 -f args.json\u3002`;
|
|
177
|
+
const message = firstError instanceof Error ? firstError.message : String(firstError);
|
|
178
|
+
throw new Error(`\u53C2\u6570\u4E0D\u662F\u6709\u6548\u7684 JSON \u6216 JS \u5BF9\u8C61: ${message}
|
|
179
|
+
${hint}`);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
function prepareRunArgsJson(args, fileContent, baseDir) {
|
|
184
|
+
let raw = "";
|
|
185
|
+
if (fileContent !== void 0) {
|
|
186
|
+
raw = fileContent.trim();
|
|
187
|
+
} else if (args.length > 0) {
|
|
188
|
+
const joined = joinShellArgs(args);
|
|
189
|
+
if (joined.startsWith("{") || looksLikeObjectBody(joined)) {
|
|
190
|
+
raw = joined;
|
|
191
|
+
} else if (args.every((arg) => arg.includes("="))) {
|
|
192
|
+
raw = buildArgsFromKeyValuePairs(args);
|
|
193
|
+
} else {
|
|
194
|
+
raw = joined;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
if (!raw) {
|
|
198
|
+
throw new Error("\u5FC5\u987B\u63D0\u4F9B\u53C2\u6570\u6216\u901A\u8FC7 -f/--file \u6307\u5B9A\u53C2\u6570\u6587\u4EF6");
|
|
199
|
+
}
|
|
200
|
+
const expanded = expandFileRefs(raw, baseDir);
|
|
201
|
+
return parseArgsJson(expanded);
|
|
202
|
+
}
|
|
31
203
|
|
|
32
204
|
// src/browser.ts
|
|
33
205
|
var import_puppeteer_core = __toESM(require("puppeteer-core"), 1);
|
|
34
206
|
var import_picocolors = __toESM(require("picocolors"), 1);
|
|
35
|
-
var
|
|
207
|
+
var import_fs2 = __toESM(require("fs"), 1);
|
|
36
208
|
var import_os = __toESM(require("os"), 1);
|
|
37
|
-
var
|
|
209
|
+
var import_path2 = __toESM(require("path"), 1);
|
|
38
210
|
var import_http = __toESM(require("http"), 1);
|
|
39
211
|
var import_child_process = require("child_process");
|
|
40
|
-
var
|
|
212
|
+
var import_url2 = require("url");
|
|
41
213
|
var import_meta = {};
|
|
42
|
-
var __filename = (0,
|
|
43
|
-
var __dirname =
|
|
214
|
+
var __filename = (0, import_url2.fileURLToPath)(import_meta.url);
|
|
215
|
+
var __dirname = import_path2.default.dirname(__filename);
|
|
44
216
|
var CDP_PORT = 9222;
|
|
45
217
|
var CDP_URL = `http://localhost:${CDP_PORT}`;
|
|
46
218
|
function httpGet(url, timeoutMs = 1500) {
|
|
47
|
-
return new Promise((
|
|
219
|
+
return new Promise((resolve3, reject) => {
|
|
48
220
|
const req = import_http.default.get(url, { timeout: timeoutMs }, (res) => {
|
|
49
221
|
let data = "";
|
|
50
222
|
res.on("data", (chunk) => {
|
|
@@ -52,7 +224,7 @@ function httpGet(url, timeoutMs = 1500) {
|
|
|
52
224
|
});
|
|
53
225
|
res.on("end", () => {
|
|
54
226
|
if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {
|
|
55
|
-
|
|
227
|
+
resolve3(data);
|
|
56
228
|
} else {
|
|
57
229
|
reject(new Error(`HTTP ${res.statusCode}`));
|
|
58
230
|
}
|
|
@@ -93,9 +265,9 @@ function getDefaultBrowserPath() {
|
|
|
93
265
|
const platform = import_os.default.platform();
|
|
94
266
|
if (platform === "darwin") {
|
|
95
267
|
const chromePath = "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome";
|
|
96
|
-
if (
|
|
268
|
+
if (import_fs2.default.existsSync(chromePath)) return { path: chromePath, name: "Chrome" };
|
|
97
269
|
const edgePath = "/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge";
|
|
98
|
-
if (
|
|
270
|
+
if (import_fs2.default.existsSync(edgePath)) return { path: edgePath, name: "Edge" };
|
|
99
271
|
return null;
|
|
100
272
|
} else if (platform === "win32") {
|
|
101
273
|
const chromePaths = [
|
|
@@ -103,7 +275,7 @@ function getDefaultBrowserPath() {
|
|
|
103
275
|
process.env.PROGRAMFILES + "\\Google\\Chrome\\Application\\chrome.exe",
|
|
104
276
|
process.env["PROGRAMFILES(X86)"] + "\\Google\\Chrome\\Application\\chrome.exe"
|
|
105
277
|
];
|
|
106
|
-
const foundChrome = chromePaths.find((p) =>
|
|
278
|
+
const foundChrome = chromePaths.find((p) => import_fs2.default.existsSync(p));
|
|
107
279
|
if (foundChrome) return { path: foundChrome, name: "Chrome" };
|
|
108
280
|
const edgePaths = [
|
|
109
281
|
process.env.LOCALAPPDATA + "\\Microsoft\\Edge\\Application\\msedge.exe",
|
|
@@ -112,7 +284,7 @@ function getDefaultBrowserPath() {
|
|
|
112
284
|
"C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe",
|
|
113
285
|
"C:\\Program Files\\Microsoft\\Edge\\Application\\msedge.exe"
|
|
114
286
|
];
|
|
115
|
-
const foundEdge = edgePaths.find((p) =>
|
|
287
|
+
const foundEdge = edgePaths.find((p) => import_fs2.default.existsSync(p));
|
|
116
288
|
if (foundEdge) return { path: foundEdge, name: "Edge" };
|
|
117
289
|
return null;
|
|
118
290
|
} else {
|
|
@@ -124,17 +296,17 @@ function getDefaultBrowserPath() {
|
|
|
124
296
|
{ p: "/usr/bin/microsoft-edge", name: "Edge" },
|
|
125
297
|
{ p: "/usr/bin/microsoft-edge-stable", name: "Edge" }
|
|
126
298
|
];
|
|
127
|
-
const found = paths.find(({ p }) =>
|
|
299
|
+
const found = paths.find(({ p }) => import_fs2.default.existsSync(p));
|
|
128
300
|
return found ? { path: found.p, name: found.name } : null;
|
|
129
301
|
}
|
|
130
302
|
}
|
|
131
303
|
async function startBrowserInBackground() {
|
|
132
304
|
const browserInfo = getDefaultBrowserPath();
|
|
133
|
-
if (!browserInfo || !
|
|
305
|
+
if (!browserInfo || !import_fs2.default.existsSync(browserInfo.path)) {
|
|
134
306
|
throw new Error("\u65E0\u6CD5\u5728\u7CFB\u7EDF\u4E2D\u627E\u5230 Chrome \u6216 Edge \u6D4F\u89C8\u5668\u7684\u9ED8\u8BA4\u5B89\u88C5\u8DEF\u5F84\u3002");
|
|
135
307
|
}
|
|
136
308
|
console.log(import_picocolors.default.yellow(`\u6B63\u5728\u542F\u52A8\u540E\u53F0 ${browserInfo.name} \u5B9E\u4F8B (\u7AEF\u53E3: ${CDP_PORT})...`));
|
|
137
|
-
const userDataDir = process.env.WEBMCP_WORKSPACE ||
|
|
309
|
+
const userDataDir = process.env.WEBMCP_WORKSPACE || import_path2.default.join(import_os.default.homedir(), ".webmcp_chrome_profile");
|
|
138
310
|
const child = (0, import_child_process.spawn)(
|
|
139
311
|
browserInfo.path,
|
|
140
312
|
[
|
|
@@ -162,7 +334,7 @@ async function startBrowserInBackground() {
|
|
|
162
334
|
}
|
|
163
335
|
} catch (e) {
|
|
164
336
|
}
|
|
165
|
-
await new Promise((
|
|
337
|
+
await new Promise((resolve3) => setTimeout(resolve3, 500));
|
|
166
338
|
}
|
|
167
339
|
throw new Error(`${browserInfo.name} \u542F\u52A8\u8D85\u65F6\uFF0C\u65E0\u6CD5\u8FDE\u63A5\u5230 CDP \u7AEF\u53E3\u3002`);
|
|
168
340
|
}
|
|
@@ -345,18 +517,18 @@ async function injectWebMCPPolyfillAndTools(page2, force = false) {
|
|
|
345
517
|
}).catch(() => false);
|
|
346
518
|
if (!polyfillReady) {
|
|
347
519
|
console.log(import_picocolors.default.cyan("\u5F53\u524D\u9875\u9762\u5C1A\u672A\u6CE8\u5165 WebMCP \u73AF\u5883\uFF0C\u6B63\u5728\u6267\u884C\u81EA\u52A8\u6CE8\u5165..."));
|
|
348
|
-
const injectScriptPath =
|
|
349
|
-
if (!
|
|
520
|
+
const injectScriptPath = import_path2.default.resolve(__dirname, "inject-bundle.js");
|
|
521
|
+
if (!import_fs2.default.existsSync(injectScriptPath)) {
|
|
350
522
|
throw new Error(`Cannot find inject-bundle.js at ${injectScriptPath}. Please ensure you run 'pnpm build:inject' first.`);
|
|
351
523
|
}
|
|
352
|
-
const scriptContent =
|
|
524
|
+
const scriptContent = import_fs2.default.readFileSync(injectScriptPath, "utf-8");
|
|
353
525
|
try {
|
|
354
526
|
await page2.evaluate(scriptContent);
|
|
355
527
|
} catch (err) {
|
|
356
528
|
const msg = err instanceof Error ? err.message : String(err);
|
|
357
529
|
throw new Error("\u81EA\u52A8\u6CE8\u5165\u811A\u672C\u6267\u884C\u5931\u8D25: " + msg);
|
|
358
530
|
}
|
|
359
|
-
await new Promise((
|
|
531
|
+
await new Promise((resolve3) => setTimeout(resolve3, 300));
|
|
360
532
|
}
|
|
361
533
|
await injectDomainTools(page2);
|
|
362
534
|
}
|
|
@@ -368,12 +540,12 @@ async function injectDomainTools(page2) {
|
|
|
368
540
|
} catch {
|
|
369
541
|
return;
|
|
370
542
|
}
|
|
371
|
-
const toolBundlePath =
|
|
372
|
-
if (!
|
|
543
|
+
const toolBundlePath = import_path2.default.resolve(__dirname, "webmcp-tools", `${hostname}.js`);
|
|
544
|
+
if (!import_fs2.default.existsSync(toolBundlePath)) {
|
|
373
545
|
return;
|
|
374
546
|
}
|
|
375
547
|
console.log(import_picocolors.default.cyan(`\u68C0\u6D4B\u5230\u57DF\u540D ${hostname} \u6709\u9884\u7F6E\u5DE5\u5177\uFF0C\u6B63\u5728\u6CE8\u5165...`));
|
|
376
|
-
const toolScript =
|
|
548
|
+
const toolScript = import_fs2.default.readFileSync(toolBundlePath, "utf-8");
|
|
377
549
|
try {
|
|
378
550
|
await page2.evaluate(toolScript);
|
|
379
551
|
console.log(import_picocolors.default.green(`\u5DF2\u4E3A ${hostname} \u6CE8\u5165\u9884\u7F6E\u5DE5\u5177`));
|
|
@@ -444,7 +616,7 @@ async function stateCommand({ tabid: tabid2 }) {
|
|
|
444
616
|
if (pUrl.startsWith("devtools://")) return null;
|
|
445
617
|
const pTitle = await Promise.race([
|
|
446
618
|
p.title().catch(() => "Unknown"),
|
|
447
|
-
new Promise((
|
|
619
|
+
new Promise((resolve3) => setTimeout(() => resolve3("Unknown"), 500))
|
|
448
620
|
]);
|
|
449
621
|
return {
|
|
450
622
|
// 使用真实的 Chrome target ID,而非数组下标
|
|
@@ -472,11 +644,7 @@ async function runCommand({
|
|
|
472
644
|
const browser2 = await connectBrowser();
|
|
473
645
|
try {
|
|
474
646
|
const page2 = await getTargetPage(browser2, tabid2);
|
|
475
|
-
|
|
476
|
-
JSON.parse(argsJson);
|
|
477
|
-
} catch (e) {
|
|
478
|
-
throw new Error(`\u53C2\u6570\u4E0D\u662F\u6709\u6548\u7684 JSON: ${e.message}`);
|
|
479
|
-
}
|
|
647
|
+
const cleanedArgs = argsJson.trim();
|
|
480
648
|
const result2 = await page2.evaluate(async (name, inputString) => {
|
|
481
649
|
const mcp = navigator.modelContextTesting || navigator.modelContext;
|
|
482
650
|
if (!mcp || typeof mcp.executeTool !== "function") {
|
|
@@ -486,11 +654,18 @@ async function runCommand({
|
|
|
486
654
|
if (typeof res === "string") {
|
|
487
655
|
try {
|
|
488
656
|
res = JSON.parse(res);
|
|
489
|
-
} catch
|
|
657
|
+
} catch {
|
|
490
658
|
}
|
|
491
659
|
}
|
|
660
|
+
if (res === void 0 || res === null) {
|
|
661
|
+
throw new Error("\u5DE5\u5177 execute \u672A\u8FD4\u56DE\u7ED3\u679C\uFF0C\u8BF7\u68C0\u67E5\u5DE5\u5177\u5B9E\u73B0\u662F\u5426\u7F3A\u5C11 return");
|
|
662
|
+
}
|
|
663
|
+
if (typeof res === "object" && res.success === false) {
|
|
664
|
+
const failed = res;
|
|
665
|
+
throw new Error(failed.error || failed.message || "\u5DE5\u5177\u6267\u884C\u5931\u8D25");
|
|
666
|
+
}
|
|
492
667
|
return res;
|
|
493
|
-
}, toolName,
|
|
668
|
+
}, toolName, cleanedArgs);
|
|
494
669
|
return result2;
|
|
495
670
|
} finally {
|
|
496
671
|
await browser2.disconnect();
|
|
@@ -550,7 +725,7 @@ async function tabsOpenCommand(url) {
|
|
|
550
725
|
url = normalizeUrl(url);
|
|
551
726
|
await page2.goto(url, { waitUntil: "domcontentloaded" });
|
|
552
727
|
await injectIntoPage(page2);
|
|
553
|
-
await new Promise((
|
|
728
|
+
await new Promise((resolve3) => setTimeout(resolve3, 500));
|
|
554
729
|
return {
|
|
555
730
|
success: true,
|
|
556
731
|
tabid: await getPageTargetId(page2),
|
|
@@ -651,7 +826,7 @@ async function tabsForwardCommand(tabid2) {
|
|
|
651
826
|
// package.json
|
|
652
827
|
var package_default = {
|
|
653
828
|
name: "@opentiny/webmcp-cli",
|
|
654
|
-
version: "0.0.1-alpha.
|
|
829
|
+
version: "0.0.1-alpha.6",
|
|
655
830
|
type: "module",
|
|
656
831
|
description: "WebMCP CLI for AI Agents to interact with browser via Puppeteer",
|
|
657
832
|
main: "dist/index.js",
|
|
@@ -690,6 +865,7 @@ var package_default = {
|
|
|
690
865
|
"@page-agent/page-controller": "catalog:",
|
|
691
866
|
clipboardy: "^5.3.1",
|
|
692
867
|
commander: "^11.1.0",
|
|
868
|
+
json5: "^2.2.3",
|
|
693
869
|
picocolors: "^1.0.0",
|
|
694
870
|
"puppeteer-core": "^22.0.0"
|
|
695
871
|
},
|
|
@@ -713,19 +889,6 @@ function handleCommandError(error, commandName) {
|
|
|
713
889
|
console.error(import_picocolors2.default.red(`Error executing ${commandName} command: ${msg}`));
|
|
714
890
|
process.exit(1);
|
|
715
891
|
}
|
|
716
|
-
function expandFileRefs(argsJson) {
|
|
717
|
-
return argsJson.replace(/"@(base64)?file:([^"]+)"/g, (_match, base64Flag, filePath) => {
|
|
718
|
-
const absPath = (0, import_path2.resolve)(process.cwd(), filePath);
|
|
719
|
-
let content;
|
|
720
|
-
try {
|
|
721
|
-
content = (0, import_fs2.readFileSync)(absPath, "utf-8");
|
|
722
|
-
} catch (e) {
|
|
723
|
-
throw new Error(`\u65E0\u6CD5\u8BFB\u53D6\u6587\u4EF6\u5F15\u7528 "${filePath}": ${e.message}`);
|
|
724
|
-
}
|
|
725
|
-
const value = base64Flag ? Buffer.from(content, "utf-8").toString("base64") : content;
|
|
726
|
-
return JSON.stringify(value);
|
|
727
|
-
});
|
|
728
|
-
}
|
|
729
892
|
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) => {
|
|
730
893
|
const opts = thisCommand.opts();
|
|
731
894
|
if (opts.workspace) {
|
|
@@ -740,28 +903,27 @@ program.command("state").description("\u83B7\u53D6\u6D4F\u89C8\u5668\u5F53\u524D
|
|
|
740
903
|
handleCommandError(error, "state");
|
|
741
904
|
}
|
|
742
905
|
});
|
|
743
|
-
program.command("run <toolName> [
|
|
906
|
+
program.command("run <toolName> [args...]").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(
|
|
744
907
|
"-f, --file <path>",
|
|
745
|
-
`\u4ECE\u6307\u5B9A .json \u6587\u4EF6\u8BFB\u53D6\u6574\u4E2A
|
|
746
|
-
\u5982\u9700\u5728
|
|
908
|
+
`\u4ECE\u6307\u5B9A .json \u6587\u4EF6\u8BFB\u53D6\u6574\u4E2A\u53C2\u6570\uFF08\u6587\u4EF6\u5185\u5BB9\u5373\u4E3A\u53C2\u6570 JSON\uFF09\u3002
|
|
909
|
+
\u5982\u9700\u5728\u53C2\u6570\u4E2D\u5185\u8054\u5F15\u7528\u6587\u4EF6\uFF0C\u4F7F\u7528\u5360\u4F4D\u7B26\u8BED\u6CD5\uFF1A
|
|
747
910
|
@file:<path> \u8BFB\u53D6\u6587\u4EF6\u539F\u59CB\u6587\u672C
|
|
748
911
|
@base64file:<path> \u8BFB\u53D6\u6587\u4EF6\u5E76 Base64 \u7F16\u7801
|
|
749
912
|
\u793A\u4F8B\uFF1Awebmcp-cli run mytool '{"content":"@base64file:./doc.md"}'`
|
|
750
|
-
).action(async (toolName,
|
|
913
|
+
).action(async (toolName, args, options) => {
|
|
751
914
|
try {
|
|
752
|
-
let
|
|
915
|
+
let fileContent;
|
|
916
|
+
let fileBaseDir = process.cwd();
|
|
753
917
|
if (options.file) {
|
|
754
|
-
const filePath = (0,
|
|
918
|
+
const filePath = (0, import_path3.resolve)(process.cwd(), options.file);
|
|
919
|
+
fileBaseDir = getFileBaseDir(options.file);
|
|
755
920
|
try {
|
|
756
|
-
|
|
921
|
+
fileContent = (0, import_fs3.readFileSync)(filePath, "utf-8");
|
|
757
922
|
} catch (e) {
|
|
758
923
|
throw new Error(`\u65E0\u6CD5\u8BFB\u53D6\u6587\u4EF6 "${filePath}": ${e.message}`);
|
|
759
924
|
}
|
|
760
925
|
}
|
|
761
|
-
|
|
762
|
-
throw new Error("\u5FC5\u987B\u63D0\u4F9B argsJson \u53C2\u6570\u6216\u901A\u8FC7 -f/--file \u6307\u5B9A\u53C2\u6570\u6587\u4EF6");
|
|
763
|
-
}
|
|
764
|
-
finalArgsJson = expandFileRefs(finalArgsJson);
|
|
926
|
+
const finalArgsJson = prepareRunArgsJson(args ?? [], fileContent, fileBaseDir);
|
|
765
927
|
const result2 = await runCommand({
|
|
766
928
|
toolName,
|
|
767
929
|
argsJson: finalArgsJson,
|