@opentiny/webmcp-cli 0.0.4 → 0.0.8
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/README.md +18 -1
- package/dist/bin.cjs +188 -54
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +188 -54
- package/dist/bin.js.map +1 -1
- package/dist/index.cjs +107 -40
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +107 -40
- package/dist/index.js.map +1 -1
- package/dist/inject-bundle.js +3860 -2035
- package/dist/webmcp-tools/creator.xiaohongshu.com.js +1 -1
- package/dist/webmcp-tools/editor.csdn.net.js +200 -10
- package/dist/webmcp-tools/excalidraw.com.js +1 -1
- package/dist/webmcp-tools/juejin.cn.js +24455 -9
- package/dist/webmcp-tools/my.oschina.net.js +176 -34
- package/dist/webmcp-tools/segmentfault.com.js +1012 -0
- package/dist/webmcp-tools/www.baidu.com.js +1 -1
- package/dist/webmcp-tools/xiaohongshu.com.js +1 -1
- package/dist/webmcp-tools/zhuanlan.zhihu.com.js +2493 -0
- package/package.json +11 -6
package/dist/bin.js
CHANGED
|
@@ -199,11 +199,37 @@ import { spawn } from "child_process";
|
|
|
199
199
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
200
200
|
var __filename = fileURLToPath2(import.meta.url);
|
|
201
201
|
var __dirname = path.dirname(__filename);
|
|
202
|
-
|
|
203
|
-
|
|
202
|
+
function getCdpPort() {
|
|
203
|
+
const raw = process.env.WEBMCP_CDP_PORT;
|
|
204
|
+
if (raw) {
|
|
205
|
+
const port = Number.parseInt(raw, 10);
|
|
206
|
+
if (Number.isFinite(port) && port > 0) return port;
|
|
207
|
+
}
|
|
208
|
+
return 9222;
|
|
209
|
+
}
|
|
204
210
|
function getWorkspaceDir() {
|
|
205
211
|
return process.env.WEBMCP_WORKSPACE || path.join(os.homedir(), ".webmcp_chrome_profile");
|
|
206
212
|
}
|
|
213
|
+
function shouldLaunchHeadless() {
|
|
214
|
+
if (process.env.WEBMCP_HEADLESS === "0") return false;
|
|
215
|
+
return process.env.WEBMCP_HEADLESS === "1" || process.env.CI === "true" || process.env.CI === "1";
|
|
216
|
+
}
|
|
217
|
+
function readActivePortFromProfile(userDataDir) {
|
|
218
|
+
try {
|
|
219
|
+
const content = fs.readFileSync(path.join(userDataDir, "DevToolsActivePort"), "utf-8");
|
|
220
|
+
const port = parseInt(content.split("\n")[0].trim(), 10);
|
|
221
|
+
return Number.isFinite(port) && port > 0 ? port : null;
|
|
222
|
+
} catch {
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
function candidateCdpBaseUrls(port) {
|
|
227
|
+
return [
|
|
228
|
+
`http://127.0.0.1:${port}`,
|
|
229
|
+
`http://[::1]:${port}`,
|
|
230
|
+
`http://localhost:${port}`
|
|
231
|
+
];
|
|
232
|
+
}
|
|
207
233
|
function getLastTabIdFilePath() {
|
|
208
234
|
return path.join(getWorkspaceDir(), ".last-tab-id");
|
|
209
235
|
}
|
|
@@ -297,6 +323,13 @@ async function connectPuppeteer(browserBaseUrl, attempt = 1, maxAttempts = 3) {
|
|
|
297
323
|
}
|
|
298
324
|
}
|
|
299
325
|
function getDefaultBrowserPath() {
|
|
326
|
+
const envPath = process.env.CHROME_PATH || process.env.WEBMCP_CHROME_PATH || process.env.PUPPETEER_EXECUTABLE_PATH;
|
|
327
|
+
if (envPath && fs.existsSync(envPath)) {
|
|
328
|
+
return { path: envPath, name: "Chrome" };
|
|
329
|
+
}
|
|
330
|
+
if (envPath) {
|
|
331
|
+
console.log(pc.yellow(`\u6307\u5B9A\u7684\u6D4F\u89C8\u5668\u8DEF\u5F84\u4E0D\u5B58\u5728\uFF0C\u5C06\u56DE\u9000\u5230\u81EA\u52A8\u68C0\u6D4B: ${envPath}`));
|
|
332
|
+
}
|
|
300
333
|
const platform = os.platform();
|
|
301
334
|
if (platform === "darwin") {
|
|
302
335
|
const chromePath = "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome";
|
|
@@ -340,16 +373,30 @@ async function startBrowserInBackground() {
|
|
|
340
373
|
if (!browserInfo || !fs.existsSync(browserInfo.path)) {
|
|
341
374
|
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");
|
|
342
375
|
}
|
|
343
|
-
|
|
344
|
-
|
|
376
|
+
const cdpPort = getCdpPort();
|
|
377
|
+
console.log(pc.yellow(`\u6B63\u5728\u542F\u52A8\u540E\u53F0 ${browserInfo.name} \u5B9E\u4F8B (\u7AEF\u53E3: ${cdpPort})...`));
|
|
378
|
+
const userDataDir = getWorkspaceDir();
|
|
379
|
+
if (!fs.existsSync(userDataDir)) {
|
|
380
|
+
fs.mkdirSync(userDataDir, { recursive: true });
|
|
381
|
+
}
|
|
382
|
+
try {
|
|
383
|
+
fs.unlinkSync(path.join(userDataDir, "DevToolsActivePort"));
|
|
384
|
+
} catch {
|
|
385
|
+
}
|
|
345
386
|
const launchArgs = [
|
|
346
|
-
`--remote-debugging-port=${
|
|
387
|
+
`--remote-debugging-port=${cdpPort}`,
|
|
347
388
|
`--user-data-dir=${userDataDir}`,
|
|
348
389
|
"--no-first-run",
|
|
349
390
|
"--no-default-browser-check"
|
|
350
391
|
];
|
|
351
|
-
if (
|
|
352
|
-
launchArgs.push(
|
|
392
|
+
if (shouldLaunchHeadless()) {
|
|
393
|
+
launchArgs.push(
|
|
394
|
+
"--headless=new",
|
|
395
|
+
"--no-sandbox",
|
|
396
|
+
"--disable-setuid-sandbox",
|
|
397
|
+
"--disable-gpu",
|
|
398
|
+
"--disable-dev-shm-usage"
|
|
399
|
+
);
|
|
353
400
|
}
|
|
354
401
|
const child = spawn(
|
|
355
402
|
browserInfo.path,
|
|
@@ -360,15 +407,22 @@ async function startBrowserInBackground() {
|
|
|
360
407
|
}
|
|
361
408
|
);
|
|
362
409
|
child.unref();
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
410
|
+
for (let i = 0; i < 40; i++) {
|
|
411
|
+
const ports = /* @__PURE__ */ new Set([cdpPort]);
|
|
412
|
+
const activePort = readActivePortFromProfile(userDataDir);
|
|
413
|
+
if (activePort) ports.add(activePort);
|
|
414
|
+
for (const port of ports) {
|
|
415
|
+
for (const baseUrl of candidateCdpBaseUrls(port)) {
|
|
416
|
+
try {
|
|
417
|
+
await httpGet(`${baseUrl}/json/version`, 1e3);
|
|
418
|
+
if (port !== cdpPort) {
|
|
419
|
+
console.log(pc.yellow(`\u68C0\u6D4B\u5230\u7AEF\u53E3 ${cdpPort} \u5DF2\u88AB\u5176\u4ED6\u7A0B\u5E8F\u5360\u7528\uFF0C${browserInfo.name} \u5DF2\u81EA\u52A8\u5207\u6362\u5230\u7AEF\u53E3 ${port}\u3002`));
|
|
420
|
+
}
|
|
421
|
+
console.log(pc.green(`${browserInfo.name} \u542F\u52A8\u5E76\u5C31\u7EEA\uFF08${baseUrl}\uFF09\u3002`));
|
|
422
|
+
await new Promise((resolve3) => setTimeout(resolve3, 500));
|
|
423
|
+
return baseUrl;
|
|
424
|
+
} catch {
|
|
425
|
+
}
|
|
372
426
|
}
|
|
373
427
|
}
|
|
374
428
|
await new Promise((resolve3) => setTimeout(resolve3, 500));
|
|
@@ -376,13 +430,16 @@ async function startBrowserInBackground() {
|
|
|
376
430
|
throw new Error(`${browserInfo.name} \u542F\u52A8\u8D85\u65F6\uFF0C\u65E0\u6CD5\u8FDE\u63A5\u5230 CDP \u7AEF\u53E3\u3002`);
|
|
377
431
|
}
|
|
378
432
|
async function connectBrowser() {
|
|
433
|
+
const userDataDir = getWorkspaceDir();
|
|
434
|
+
const cdpPort = getCdpPort();
|
|
435
|
+
const recordedPort = readActivePortFromProfile(userDataDir);
|
|
379
436
|
const versionAddresses = [
|
|
380
|
-
|
|
381
|
-
|
|
437
|
+
...recordedPort && recordedPort !== cdpPort ? candidateCdpBaseUrls(recordedPort).map((u) => `${u}/json/version`) : [],
|
|
438
|
+
...candidateCdpBaseUrls(cdpPort).map((u) => `${u}/json/version`)
|
|
382
439
|
];
|
|
383
440
|
const existingUrl = await findAvailableCdpUrl(versionAddresses, 2);
|
|
384
441
|
if (existingUrl) {
|
|
385
|
-
console.log(pc.yellow(`connectBrowser: \u68C0\u6D4B\u5230\u7AEF\u53E3 ${
|
|
442
|
+
console.log(pc.yellow(`connectBrowser: \u68C0\u6D4B\u5230\u7AEF\u53E3 ${cdpPort} \u5DF2\u5C31\u7EEA\uFF0C\u6B63\u5728\u8FDE\u63A5 ${existingUrl}...`));
|
|
386
443
|
try {
|
|
387
444
|
const browser = await connectPuppeteer(existingUrl);
|
|
388
445
|
console.log(pc.green(`connectBrowser: \u6210\u529F\u8FDE\u63A5 ${existingUrl}`));
|
|
@@ -394,25 +451,22 @@ async function connectBrowser() {
|
|
|
394
451
|
);
|
|
395
452
|
}
|
|
396
453
|
}
|
|
397
|
-
console.log(pc.yellow(`connectBrowser: \u7AEF\u53E3 ${
|
|
454
|
+
console.log(pc.yellow(`connectBrowser: \u7AEF\u53E3 ${cdpPort} \u65E0\u54CD\u5E94\uFF0C\u6B63\u5728\u542F\u52A8\u65B0\u7684\u6D4F\u89C8\u5668\u5B9E\u4F8B...`));
|
|
455
|
+
let launchedUrl;
|
|
398
456
|
try {
|
|
399
|
-
await startBrowserInBackground();
|
|
457
|
+
launchedUrl = await startBrowserInBackground();
|
|
400
458
|
} catch (launchError) {
|
|
401
459
|
const msg = launchError instanceof Error ? launchError.message : String(launchError);
|
|
402
460
|
console.error(pc.red(`\u65E0\u6CD5\u542F\u52A8\u6D4F\u89C8\u5668: ${msg}`));
|
|
403
461
|
throw new Error("Browser launch failed.");
|
|
404
462
|
}
|
|
405
|
-
const launchedUrl = await findAvailableCdpUrl(versionAddresses, 5);
|
|
406
|
-
if (!launchedUrl) {
|
|
407
|
-
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`);
|
|
408
|
-
}
|
|
409
463
|
try {
|
|
410
464
|
console.log(pc.yellow(`connectBrowser: \u6D4F\u89C8\u5668\u5DF2\u542F\u52A8\uFF0C\u6B63\u5728\u8FDE\u63A5 ${launchedUrl}...`));
|
|
411
465
|
const browser = await connectPuppeteer(launchedUrl);
|
|
412
466
|
console.log(pc.green(`connectBrowser: \u6210\u529F\u8FDE\u63A5 ${launchedUrl}`));
|
|
413
467
|
return browser;
|
|
414
468
|
} catch {
|
|
415
|
-
throw new Error(`\u65E0\u6CD5\u8FDE\u63A5\u5230\u6D4F\u89C8\u5668\uFF08
|
|
469
|
+
throw new Error(`\u65E0\u6CD5\u8FDE\u63A5\u5230\u6D4F\u89C8\u5668\uFF08${launchedUrl}\uFF09\uFF0C\u8BF7\u68C0\u67E5 Chrome/Edge \u662F\u5426\u5DF2\u5B89\u88C5\u3002`);
|
|
416
470
|
}
|
|
417
471
|
}
|
|
418
472
|
async function getPageTargetId(page) {
|
|
@@ -492,10 +546,11 @@ async function getTargetPage(browser, tabid) {
|
|
|
492
546
|
}
|
|
493
547
|
if (!targetPage) {
|
|
494
548
|
try {
|
|
495
|
-
const
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
];
|
|
549
|
+
const workspaceDir = getWorkspaceDir();
|
|
550
|
+
const cdpPort = getCdpPort();
|
|
551
|
+
const recordedPort = readActivePortFromProfile(workspaceDir);
|
|
552
|
+
const ports = recordedPort && recordedPort !== cdpPort ? [recordedPort, cdpPort] : [cdpPort];
|
|
553
|
+
const urls = ports.flatMap((port) => candidateCdpBaseUrls(port).map((u) => `${u}/json/list`));
|
|
499
554
|
let activeTargetId = null;
|
|
500
555
|
for (const url of urls) {
|
|
501
556
|
try {
|
|
@@ -532,10 +587,10 @@ async function getTargetPage(browser, tabid) {
|
|
|
532
587
|
return targetPage;
|
|
533
588
|
}
|
|
534
589
|
async function injectIntoPage(page) {
|
|
535
|
-
await injectWebMCPPolyfillAndTools(page
|
|
590
|
+
await injectWebMCPPolyfillAndTools(page);
|
|
536
591
|
}
|
|
537
|
-
async function injectWebMCPPolyfillAndTools(page
|
|
538
|
-
const polyfillReady =
|
|
592
|
+
async function injectWebMCPPolyfillAndTools(page) {
|
|
593
|
+
const polyfillReady = await page.evaluate(() => {
|
|
539
594
|
return !!window.__webmcpcli_init;
|
|
540
595
|
}).catch(() => false);
|
|
541
596
|
if (!polyfillReady) {
|
|
@@ -625,11 +680,19 @@ async function stateCommand({ tabid }) {
|
|
|
625
680
|
const state = await page.evaluate(async () => {
|
|
626
681
|
const url = document.URL;
|
|
627
682
|
const title = document.title;
|
|
628
|
-
const mcp =
|
|
683
|
+
const mcp = document.modelContext || navigator.modelContext;
|
|
629
684
|
let webmcpTools = [];
|
|
630
|
-
if (mcp && typeof mcp.
|
|
631
|
-
|
|
632
|
-
|
|
685
|
+
if (mcp && typeof mcp.getTools === "function") {
|
|
686
|
+
try {
|
|
687
|
+
const toolsResult = await mcp.getTools();
|
|
688
|
+
const list = toolsResult?.tools || toolsResult || [];
|
|
689
|
+
webmcpTools = list.filter((t) => t && typeof t.name === "string").map((t) => ({
|
|
690
|
+
name: t.name,
|
|
691
|
+
description: typeof t.description === "string" ? t.description.slice(0, 200) : void 0
|
|
692
|
+
}));
|
|
693
|
+
} catch {
|
|
694
|
+
webmcpTools = [];
|
|
695
|
+
}
|
|
633
696
|
}
|
|
634
697
|
return { url, title, webmcpTools };
|
|
635
698
|
});
|
|
@@ -671,15 +734,19 @@ async function runCommand({
|
|
|
671
734
|
try {
|
|
672
735
|
const page = await getTargetPage(browser, tabid);
|
|
673
736
|
const urlBefore = page.url();
|
|
737
|
+
await injectIntoPage(page);
|
|
674
738
|
const cleanedArgs = argsJson.trim();
|
|
675
739
|
let result;
|
|
676
740
|
try {
|
|
677
741
|
result = await page.evaluate(async (name, inputString) => {
|
|
678
|
-
const mcp =
|
|
742
|
+
const mcp = document.modelContext || document.modelContext || document.modelContext;
|
|
679
743
|
if (!mcp || typeof mcp.executeTool !== "function") {
|
|
680
|
-
throw new Error("\u5F53\u524D\u9875\u9762\u6CA1\u6709\u6CE8\u5165 WebMCP \u73AF\u5883 (
|
|
744
|
+
throw new Error("\u5F53\u524D\u9875\u9762\u6CA1\u6709\u6CE8\u5165 WebMCP \u73AF\u5883 (document.modelContext \u672A\u627E\u5230)");
|
|
681
745
|
}
|
|
682
|
-
|
|
746
|
+
const tools = await mcp.getTools();
|
|
747
|
+
const toolObj = tools.find((t) => t.name === name);
|
|
748
|
+
if (!toolObj) throw new Error(`Tool ${name} not found`);
|
|
749
|
+
let res = await mcp.executeTool(toolObj, inputString);
|
|
683
750
|
if (typeof res === "string") {
|
|
684
751
|
try {
|
|
685
752
|
res = JSON.parse(res);
|
|
@@ -856,7 +923,7 @@ async function tabsForwardCommand(tabid) {
|
|
|
856
923
|
// package.json
|
|
857
924
|
var package_default = {
|
|
858
925
|
name: "@opentiny/webmcp-cli",
|
|
859
|
-
version: "0.0.
|
|
926
|
+
version: "0.0.8",
|
|
860
927
|
type: "module",
|
|
861
928
|
description: "WebMCP CLI for AI Agents to interact with browser via Puppeteer",
|
|
862
929
|
main: "dist/index.js",
|
|
@@ -874,7 +941,10 @@ var package_default = {
|
|
|
874
941
|
build: "tsup && pnpm run build:inject",
|
|
875
942
|
prepublishOnly: "pnpm run build",
|
|
876
943
|
"link:global": "npm install -g .",
|
|
877
|
-
start: "node dist/bin.js"
|
|
944
|
+
start: "node dist/bin.js",
|
|
945
|
+
test: "vitest run",
|
|
946
|
+
"test:watch": "vitest",
|
|
947
|
+
"test:browser": "vitest run --config vitest.e2e.config.ts"
|
|
878
948
|
},
|
|
879
949
|
keywords: [
|
|
880
950
|
"chrome",
|
|
@@ -896,6 +966,7 @@ var package_default = {
|
|
|
896
966
|
clipboardy: "^5.3.1",
|
|
897
967
|
commander: "^11.1.0",
|
|
898
968
|
json5: "^2.2.3",
|
|
969
|
+
marked: "^15.0.7",
|
|
899
970
|
picocolors: "^1.0.0",
|
|
900
971
|
"puppeteer-core": "^22.0.0"
|
|
901
972
|
},
|
|
@@ -904,7 +975,8 @@ var package_default = {
|
|
|
904
975
|
esbuild: "^0.25.0",
|
|
905
976
|
tsup: "^8.0.2",
|
|
906
977
|
tsx: "^4.0.0",
|
|
907
|
-
typescript: "^5.3.3"
|
|
978
|
+
typescript: "^5.3.3",
|
|
979
|
+
vitest: "^4.1.10"
|
|
908
980
|
}
|
|
909
981
|
};
|
|
910
982
|
|
|
@@ -914,6 +986,30 @@ function parseTabId(id) {
|
|
|
914
986
|
if (!id) return void 0;
|
|
915
987
|
return id;
|
|
916
988
|
}
|
|
989
|
+
function tryParseBrowserStateText(text) {
|
|
990
|
+
const tryParse = (jsonStr) => {
|
|
991
|
+
try {
|
|
992
|
+
const parsed = JSON.parse(jsonStr);
|
|
993
|
+
if (parsed && typeof parsed.content === "string") {
|
|
994
|
+
return parsed;
|
|
995
|
+
}
|
|
996
|
+
} catch {
|
|
997
|
+
}
|
|
998
|
+
return null;
|
|
999
|
+
};
|
|
1000
|
+
const direct = tryParse(text);
|
|
1001
|
+
if (direct) return direct;
|
|
1002
|
+
if (text.startsWith("\u6D4F\u89C8\u5668\u72B6\u6001: ")) {
|
|
1003
|
+
let jsonStr = text.substring("\u6D4F\u89C8\u5668\u72B6\u6001: ".length);
|
|
1004
|
+
const firstNewline = jsonStr.indexOf("\n");
|
|
1005
|
+
if (firstNewline !== -1) {
|
|
1006
|
+
const maybeJson = jsonStr.substring(0, firstNewline);
|
|
1007
|
+
if (tryParse(maybeJson)) jsonStr = maybeJson;
|
|
1008
|
+
}
|
|
1009
|
+
return tryParse(jsonStr);
|
|
1010
|
+
}
|
|
1011
|
+
return null;
|
|
1012
|
+
}
|
|
917
1013
|
function cleanOldLogs(baseDir, logDir) {
|
|
918
1014
|
try {
|
|
919
1015
|
const oldLogFile = path2.join(baseDir, "webmcp-cli.log");
|
|
@@ -956,6 +1052,51 @@ function cleanOldLogs(baseDir, logDir) {
|
|
|
956
1052
|
} catch (e) {
|
|
957
1053
|
}
|
|
958
1054
|
}
|
|
1055
|
+
function formatLogResult(result) {
|
|
1056
|
+
if (result === void 0 || result === null) {
|
|
1057
|
+
return "null";
|
|
1058
|
+
}
|
|
1059
|
+
try {
|
|
1060
|
+
if (typeof result !== "object") {
|
|
1061
|
+
return String(result);
|
|
1062
|
+
}
|
|
1063
|
+
const clone = JSON.parse(JSON.stringify(result));
|
|
1064
|
+
let a11yTreeStr = "";
|
|
1065
|
+
let searchResultStr = "";
|
|
1066
|
+
if (clone && Array.isArray(clone.content) && clone.content.length > 0 && clone.content[0] && typeof clone.content[0].text === "string") {
|
|
1067
|
+
const text = clone.content[0].text;
|
|
1068
|
+
const browserState = tryParseBrowserStateText(text);
|
|
1069
|
+
if (browserState) {
|
|
1070
|
+
a11yTreeStr = browserState.content;
|
|
1071
|
+
browserState.content = "[Formatted A11y Tree - See details below]";
|
|
1072
|
+
clone.content[0].text = JSON.stringify(browserState, null, 2);
|
|
1073
|
+
} else if (text.includes("A11y Tree \u641C\u7D22\u7ED3\u679C") || text.includes("\u65E0\u969C\u788D\u6811\u641C\u7D22\u7ED3\u679C") || text.includes("\u65E0\u969C\u788D\u6811\u641C\u7D22") || text.includes("\u547D\u4E2D\u884C") || text.includes("context:")) {
|
|
1074
|
+
searchResultStr = text;
|
|
1075
|
+
clone.content[0].text = "[Search A11y Tree Result - See details below]";
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
let out = JSON.stringify(clone, null, 2);
|
|
1079
|
+
if (a11yTreeStr) {
|
|
1080
|
+
out += `
|
|
1081
|
+
|
|
1082
|
+
[FORMATTED A11Y TREE]:
|
|
1083
|
+
${a11yTreeStr}`;
|
|
1084
|
+
}
|
|
1085
|
+
if (searchResultStr) {
|
|
1086
|
+
out += `
|
|
1087
|
+
|
|
1088
|
+
[FORMATTED SEARCH RESULT]:
|
|
1089
|
+
${searchResultStr}`;
|
|
1090
|
+
}
|
|
1091
|
+
return out;
|
|
1092
|
+
} catch (e) {
|
|
1093
|
+
try {
|
|
1094
|
+
return JSON.stringify(result, null, 2);
|
|
1095
|
+
} catch {
|
|
1096
|
+
return String(result);
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
959
1100
|
function writeLog(commandName, args, result, error) {
|
|
960
1101
|
try {
|
|
961
1102
|
const baseDir = process.env.WEBMCP_WORKSPACE || path2.join(os2.homedir(), ".webmcp_chrome_profile");
|
|
@@ -981,15 +1122,8 @@ ${error instanceof Error ? error.stack : String(error)}
|
|
|
981
1122
|
} else if (result) {
|
|
982
1123
|
logText += `RESULT:
|
|
983
1124
|
`;
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
logText += JSON.stringify(result, null, 2).split("\n").map((line) => ` ${line}`).join("\n") + "\n";
|
|
987
|
-
} else {
|
|
988
|
-
logText += String(result).split("\n").map((line) => ` ${line}`).join("\n") + "\n";
|
|
989
|
-
}
|
|
990
|
-
} catch {
|
|
991
|
-
logText += JSON.stringify(result, null, 2).split("\n").map((line) => ` ${line}`).join("\n") + "\n";
|
|
992
|
-
}
|
|
1125
|
+
const formattedResult = formatLogResult(result);
|
|
1126
|
+
logText += formattedResult.split("\n").map((line) => ` ${line}`).join("\n") + "\n";
|
|
993
1127
|
} else {
|
|
994
1128
|
logText += `RESULT: null
|
|
995
1129
|
`;
|
|
@@ -1019,7 +1153,7 @@ program.command("state").description("\u83B7\u53D6\u6D4F\u89C8\u5668\u5F53\u524D
|
|
|
1019
1153
|
try {
|
|
1020
1154
|
const result = await stateCommand(args);
|
|
1021
1155
|
writeLog("state", args, result);
|
|
1022
|
-
console.log(
|
|
1156
|
+
console.log(formatLogResult(result));
|
|
1023
1157
|
} catch (error) {
|
|
1024
1158
|
handleCommandError(error, "state", args);
|
|
1025
1159
|
}
|
|
@@ -1053,7 +1187,7 @@ program.command("run <toolName> [args...]").description("\u5411\u6307\u5B9A\u987
|
|
|
1053
1187
|
tabid: parseTabId(options.tabid)
|
|
1054
1188
|
});
|
|
1055
1189
|
writeLog("run", { ...rawArgs, finalArgsJson }, result);
|
|
1056
|
-
console.log(
|
|
1190
|
+
console.log(formatLogResult(result));
|
|
1057
1191
|
} catch (error) {
|
|
1058
1192
|
handleCommandError(error, "run", { ...rawArgs, finalArgsJson });
|
|
1059
1193
|
}
|