@opentiny/webmcp-cli 0.0.1-alpha.5 → 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 +215 -89
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +198 -72
- package/dist/bin.js.map +1 -1
- package/dist/index.cjs +10 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +10 -12
- package/dist/index.js.map +1 -1
- package/dist/webmcp-tools/juejin.cn.js +54 -21
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -3,8 +3,180 @@
|
|
|
3
3
|
// src/bin.ts
|
|
4
4
|
import { Command } from "commander";
|
|
5
5
|
import pc2 from "picocolors";
|
|
6
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
7
|
+
import { resolve as resolve2 } from "path";
|
|
8
|
+
|
|
9
|
+
// src/expand-file-refs.ts
|
|
6
10
|
import { readFileSync } from "fs";
|
|
7
|
-
import { resolve } from "path";
|
|
11
|
+
import { dirname, isAbsolute, normalize, resolve } from "path";
|
|
12
|
+
import { fileURLToPath } from "url";
|
|
13
|
+
var JSON_STRING_LITERAL = /"(?:[^"\\]|\\.)*"/g;
|
|
14
|
+
var UNQUOTED_FILE_REF = /(?<![\\"])@(base64)?file:([^\s"',}\]]+)/g;
|
|
15
|
+
var FILE_REF_PREFIX = /^@(base64)?file:(.+)$/s;
|
|
16
|
+
function resolveFilePath(filePath, baseDir = process.cwd()) {
|
|
17
|
+
let normalizedPath = filePath.trim();
|
|
18
|
+
if (normalizedPath.startsWith('"') && normalizedPath.endsWith('"') || normalizedPath.startsWith("'") && normalizedPath.endsWith("'")) {
|
|
19
|
+
normalizedPath = normalizedPath.slice(1, -1).trim();
|
|
20
|
+
}
|
|
21
|
+
if (normalizedPath.startsWith("file://")) {
|
|
22
|
+
normalizedPath = fileURLToPath(normalizedPath);
|
|
23
|
+
}
|
|
24
|
+
if (isAbsolute(normalizedPath)) {
|
|
25
|
+
return normalize(normalizedPath);
|
|
26
|
+
}
|
|
27
|
+
return resolve(baseDir, normalizedPath);
|
|
28
|
+
}
|
|
29
|
+
function decodeFilePath(rawPath) {
|
|
30
|
+
return rawPath.replace(/\\\\/g, "\\");
|
|
31
|
+
}
|
|
32
|
+
function readFileRefContent(filePath, baseDir, base64) {
|
|
33
|
+
const absPath = resolveFilePath(filePath, baseDir);
|
|
34
|
+
let content;
|
|
35
|
+
try {
|
|
36
|
+
content = readFileSync(absPath, "utf-8");
|
|
37
|
+
} catch (e) {
|
|
38
|
+
throw new Error(`\u65E0\u6CD5\u8BFB\u53D6\u6587\u4EF6\u5F15\u7528 "${filePath}" (${absPath}): ${e.message}`);
|
|
39
|
+
}
|
|
40
|
+
return base64 ? Buffer.from(content, "utf-8").toString("base64") : content;
|
|
41
|
+
}
|
|
42
|
+
function expandFileRefValue(rawInner, baseDir) {
|
|
43
|
+
const match = rawInner.match(FILE_REF_PREFIX);
|
|
44
|
+
if (!match) {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
const [, base64Flag, rawPath] = match;
|
|
48
|
+
const filePath = decodeFilePath(rawPath);
|
|
49
|
+
const value = readFileRefContent(filePath, baseDir, Boolean(base64Flag));
|
|
50
|
+
return JSON.stringify(value);
|
|
51
|
+
}
|
|
52
|
+
function expandQuotedFileRefs(argsJson, baseDir) {
|
|
53
|
+
return argsJson.replace(JSON_STRING_LITERAL, (jsonStringLiteral) => {
|
|
54
|
+
const rawInner = jsonStringLiteral.slice(1, -1);
|
|
55
|
+
const replacement = expandFileRefValue(rawInner, baseDir);
|
|
56
|
+
return replacement ?? jsonStringLiteral;
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
function expandUnquotedFileRefs(argsJson, baseDir) {
|
|
60
|
+
return argsJson.replace(UNQUOTED_FILE_REF, (match, base64Flag, filePath) => {
|
|
61
|
+
const value = readFileRefContent(filePath, baseDir, Boolean(base64Flag));
|
|
62
|
+
return JSON.stringify(value);
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
function expandFileRefs(argsJson, baseDir = process.cwd()) {
|
|
66
|
+
const withQuotedExpanded = expandQuotedFileRefs(argsJson, baseDir);
|
|
67
|
+
return expandUnquotedFileRefs(withQuotedExpanded, baseDir);
|
|
68
|
+
}
|
|
69
|
+
function getFileBaseDir(fileOption) {
|
|
70
|
+
if (!fileOption) {
|
|
71
|
+
return process.cwd();
|
|
72
|
+
}
|
|
73
|
+
return dirname(resolve(process.cwd(), fileOption));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// src/parse-run-args.ts
|
|
77
|
+
import JSON5 from "json5";
|
|
78
|
+
function cleanJsonString(str) {
|
|
79
|
+
let cleaned = str.trim();
|
|
80
|
+
if (cleaned.startsWith("'") && cleaned.endsWith("'")) {
|
|
81
|
+
cleaned = cleaned.slice(1, -1).trim();
|
|
82
|
+
}
|
|
83
|
+
return cleaned;
|
|
84
|
+
}
|
|
85
|
+
function looksLikeObjectBody(raw) {
|
|
86
|
+
return /^("?[\w-]+"?\s*:)/.test(raw);
|
|
87
|
+
}
|
|
88
|
+
function joinShellArgs(args) {
|
|
89
|
+
const cleaned = args.map(cleanJsonString);
|
|
90
|
+
const first = cleaned[0] ?? "";
|
|
91
|
+
if (first.startsWith("{")) {
|
|
92
|
+
return cleaned.join(" ");
|
|
93
|
+
}
|
|
94
|
+
if (looksLikeObjectBody(first)) {
|
|
95
|
+
let joined = cleaned.join(" ");
|
|
96
|
+
if (!joined.startsWith("{")) {
|
|
97
|
+
joined = `{${joined}}`;
|
|
98
|
+
}
|
|
99
|
+
if (!joined.endsWith("}")) {
|
|
100
|
+
joined = `${joined}}`;
|
|
101
|
+
}
|
|
102
|
+
return joined;
|
|
103
|
+
}
|
|
104
|
+
return cleaned.join(" ");
|
|
105
|
+
}
|
|
106
|
+
function insertMissingCommas(raw) {
|
|
107
|
+
return raw.replace(/"(\s+)("?[\w-]+"?\s*:)/g, '",$2');
|
|
108
|
+
}
|
|
109
|
+
function quoteUnquotedStringValues(raw) {
|
|
110
|
+
return raw.replace(
|
|
111
|
+
/([{,]\s*(?:"([^"]+)"|([\w-]+))\s*:\s*)(?!"@(?:base64)?file:|"|true|false|null|-?\d|\{|\[)([^",}\]]+?)(?=\s*[,}])/g,
|
|
112
|
+
(_match, prefix, _quotedKey, _unquotedKey, value) => {
|
|
113
|
+
const trimmed = value.trim();
|
|
114
|
+
if (/^-?\d+(\.\d+)?([eE][+-]?\d+)?$/.test(trimmed)) {
|
|
115
|
+
return prefix + trimmed;
|
|
116
|
+
}
|
|
117
|
+
return prefix + JSON.stringify(trimmed);
|
|
118
|
+
}
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
function normalizeShellDamagedJson(raw) {
|
|
122
|
+
let normalized = raw.trim();
|
|
123
|
+
normalized = insertMissingCommas(normalized);
|
|
124
|
+
normalized = quoteUnquotedStringValues(normalized);
|
|
125
|
+
return normalized;
|
|
126
|
+
}
|
|
127
|
+
function buildArgsFromKeyValuePairs(args) {
|
|
128
|
+
const obj = {};
|
|
129
|
+
for (const pair of args) {
|
|
130
|
+
const index = pair.indexOf("=");
|
|
131
|
+
if (index === -1) {
|
|
132
|
+
throw new Error(`\u65E0\u6548\u7684\u53C2\u6570\u683C\u5F0F "${pair}"\u3002\u8BF7\u4F7F\u7528 key=value\uFF0C\u6216 JSON / -f \u6587\u4EF6\u3002`);
|
|
133
|
+
}
|
|
134
|
+
const key = pair.substring(0, index).trim();
|
|
135
|
+
let val = cleanJsonString(pair.substring(index + 1).trim());
|
|
136
|
+
try {
|
|
137
|
+
obj[key] = JSON.parse(val);
|
|
138
|
+
} catch {
|
|
139
|
+
obj[key] = val;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return JSON.stringify(obj);
|
|
143
|
+
}
|
|
144
|
+
function parseArgsJson(raw) {
|
|
145
|
+
const trimmed = cleanJsonString(raw);
|
|
146
|
+
try {
|
|
147
|
+
return JSON.stringify(JSON5.parse(trimmed));
|
|
148
|
+
} catch (firstError) {
|
|
149
|
+
const repaired = normalizeShellDamagedJson(trimmed);
|
|
150
|
+
try {
|
|
151
|
+
return JSON.stringify(JSON5.parse(repaired));
|
|
152
|
+
} catch {
|
|
153
|
+
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`;
|
|
154
|
+
const message = firstError instanceof Error ? firstError.message : String(firstError);
|
|
155
|
+
throw new Error(`\u53C2\u6570\u4E0D\u662F\u6709\u6548\u7684 JSON \u6216 JS \u5BF9\u8C61: ${message}
|
|
156
|
+
${hint}`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
function prepareRunArgsJson(args, fileContent, baseDir) {
|
|
161
|
+
let raw = "";
|
|
162
|
+
if (fileContent !== void 0) {
|
|
163
|
+
raw = fileContent.trim();
|
|
164
|
+
} else if (args.length > 0) {
|
|
165
|
+
const joined = joinShellArgs(args);
|
|
166
|
+
if (joined.startsWith("{") || looksLikeObjectBody(joined)) {
|
|
167
|
+
raw = joined;
|
|
168
|
+
} else if (args.every((arg) => arg.includes("="))) {
|
|
169
|
+
raw = buildArgsFromKeyValuePairs(args);
|
|
170
|
+
} else {
|
|
171
|
+
raw = joined;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
if (!raw) {
|
|
175
|
+
throw new Error("\u5FC5\u987B\u63D0\u4F9B\u53C2\u6570\u6216\u901A\u8FC7 -f/--file \u6307\u5B9A\u53C2\u6570\u6587\u4EF6");
|
|
176
|
+
}
|
|
177
|
+
const expanded = expandFileRefs(raw, baseDir);
|
|
178
|
+
return parseArgsJson(expanded);
|
|
179
|
+
}
|
|
8
180
|
|
|
9
181
|
// src/browser.ts
|
|
10
182
|
import puppeteer from "puppeteer-core";
|
|
@@ -14,13 +186,13 @@ import os from "os";
|
|
|
14
186
|
import path from "path";
|
|
15
187
|
import http from "http";
|
|
16
188
|
import { spawn } from "child_process";
|
|
17
|
-
import { fileURLToPath } from "url";
|
|
18
|
-
var __filename =
|
|
189
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
190
|
+
var __filename = fileURLToPath2(import.meta.url);
|
|
19
191
|
var __dirname = path.dirname(__filename);
|
|
20
192
|
var CDP_PORT = 9222;
|
|
21
193
|
var CDP_URL = `http://localhost:${CDP_PORT}`;
|
|
22
194
|
function httpGet(url, timeoutMs = 1500) {
|
|
23
|
-
return new Promise((
|
|
195
|
+
return new Promise((resolve3, reject) => {
|
|
24
196
|
const req = http.get(url, { timeout: timeoutMs }, (res) => {
|
|
25
197
|
let data = "";
|
|
26
198
|
res.on("data", (chunk) => {
|
|
@@ -28,7 +200,7 @@ function httpGet(url, timeoutMs = 1500) {
|
|
|
28
200
|
});
|
|
29
201
|
res.on("end", () => {
|
|
30
202
|
if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {
|
|
31
|
-
|
|
203
|
+
resolve3(data);
|
|
32
204
|
} else {
|
|
33
205
|
reject(new Error(`HTTP ${res.statusCode}`));
|
|
34
206
|
}
|
|
@@ -138,7 +310,7 @@ async function startBrowserInBackground() {
|
|
|
138
310
|
}
|
|
139
311
|
} catch (e) {
|
|
140
312
|
}
|
|
141
|
-
await new Promise((
|
|
313
|
+
await new Promise((resolve3) => setTimeout(resolve3, 500));
|
|
142
314
|
}
|
|
143
315
|
throw new Error(`${browserInfo.name} \u542F\u52A8\u8D85\u65F6\uFF0C\u65E0\u6CD5\u8FDE\u63A5\u5230 CDP \u7AEF\u53E3\u3002`);
|
|
144
316
|
}
|
|
@@ -332,7 +504,7 @@ async function injectWebMCPPolyfillAndTools(page2, force = false) {
|
|
|
332
504
|
const msg = err instanceof Error ? err.message : String(err);
|
|
333
505
|
throw new Error("\u81EA\u52A8\u6CE8\u5165\u811A\u672C\u6267\u884C\u5931\u8D25: " + msg);
|
|
334
506
|
}
|
|
335
|
-
await new Promise((
|
|
507
|
+
await new Promise((resolve3) => setTimeout(resolve3, 300));
|
|
336
508
|
}
|
|
337
509
|
await injectDomainTools(page2);
|
|
338
510
|
}
|
|
@@ -420,7 +592,7 @@ async function stateCommand({ tabid: tabid2 }) {
|
|
|
420
592
|
if (pUrl.startsWith("devtools://")) return null;
|
|
421
593
|
const pTitle = await Promise.race([
|
|
422
594
|
p.title().catch(() => "Unknown"),
|
|
423
|
-
new Promise((
|
|
595
|
+
new Promise((resolve3) => setTimeout(() => resolve3("Unknown"), 500))
|
|
424
596
|
]);
|
|
425
597
|
return {
|
|
426
598
|
// 使用真实的 Chrome target ID,而非数组下标
|
|
@@ -440,7 +612,6 @@ async function stateCommand({ tabid: tabid2 }) {
|
|
|
440
612
|
}
|
|
441
613
|
|
|
442
614
|
// src/commands/run.ts
|
|
443
|
-
import JSON5 from "json5";
|
|
444
615
|
async function runCommand({
|
|
445
616
|
toolName,
|
|
446
617
|
argsJson,
|
|
@@ -449,16 +620,7 @@ async function runCommand({
|
|
|
449
620
|
const browser2 = await connectBrowser();
|
|
450
621
|
try {
|
|
451
622
|
const page2 = await getTargetPage(browser2, tabid2);
|
|
452
|
-
|
|
453
|
-
if (cleanedArgs.startsWith("'") && cleanedArgs.endsWith("'")) {
|
|
454
|
-
cleanedArgs = cleanedArgs.slice(1, -1).trim();
|
|
455
|
-
}
|
|
456
|
-
try {
|
|
457
|
-
const obj = JSON5.parse(cleanedArgs);
|
|
458
|
-
cleanedArgs = JSON.stringify(obj);
|
|
459
|
-
} catch (e) {
|
|
460
|
-
throw new Error(`\u53C2\u6570\u4E0D\u662F\u6709\u6548\u7684 JSON \u6216 JS \u5BF9\u8C61: ${e.message}`);
|
|
461
|
-
}
|
|
623
|
+
const cleanedArgs = argsJson.trim();
|
|
462
624
|
const result2 = await page2.evaluate(async (name, inputString) => {
|
|
463
625
|
const mcp = navigator.modelContextTesting || navigator.modelContext;
|
|
464
626
|
if (!mcp || typeof mcp.executeTool !== "function") {
|
|
@@ -468,9 +630,17 @@ async function runCommand({
|
|
|
468
630
|
if (typeof res === "string") {
|
|
469
631
|
try {
|
|
470
632
|
res = JSON.parse(res);
|
|
471
|
-
} catch
|
|
633
|
+
} catch {
|
|
472
634
|
}
|
|
473
635
|
}
|
|
636
|
+
if (res === void 0 || res === null) {
|
|
637
|
+
throw new Error("\u5DE5\u5177 execute \u672A\u8FD4\u56DE\u7ED3\u679C\uFF0C\u8BF7\u68C0\u67E5\u5DE5\u5177\u5B9E\u73B0\u662F\u5426\u7F3A\u5C11 return");
|
|
638
|
+
}
|
|
639
|
+
if (typeof res === "object" && res.success === false) {
|
|
640
|
+
const failed = res;
|
|
641
|
+
throw new Error(failed.error || failed.message || "\u5DE5\u5177\u6267\u884C\u5931\u8D25");
|
|
642
|
+
}
|
|
643
|
+
return res;
|
|
474
644
|
}, toolName, cleanedArgs);
|
|
475
645
|
return result2;
|
|
476
646
|
} finally {
|
|
@@ -531,7 +701,7 @@ async function tabsOpenCommand(url) {
|
|
|
531
701
|
url = normalizeUrl(url);
|
|
532
702
|
await page2.goto(url, { waitUntil: "domcontentloaded" });
|
|
533
703
|
await injectIntoPage(page2);
|
|
534
|
-
await new Promise((
|
|
704
|
+
await new Promise((resolve3) => setTimeout(resolve3, 500));
|
|
535
705
|
return {
|
|
536
706
|
success: true,
|
|
537
707
|
tabid: await getPageTargetId(page2),
|
|
@@ -632,7 +802,7 @@ async function tabsForwardCommand(tabid2) {
|
|
|
632
802
|
// package.json
|
|
633
803
|
var package_default = {
|
|
634
804
|
name: "@opentiny/webmcp-cli",
|
|
635
|
-
version: "0.0.1-alpha.
|
|
805
|
+
version: "0.0.1-alpha.6",
|
|
636
806
|
type: "module",
|
|
637
807
|
description: "WebMCP CLI for AI Agents to interact with browser via Puppeteer",
|
|
638
808
|
main: "dist/index.js",
|
|
@@ -686,13 +856,6 @@ var package_default = {
|
|
|
686
856
|
|
|
687
857
|
// src/bin.ts
|
|
688
858
|
var program = new Command();
|
|
689
|
-
function cleanJsonString(str) {
|
|
690
|
-
let cleaned = str.trim();
|
|
691
|
-
if (cleaned.startsWith("'") && cleaned.endsWith("'")) {
|
|
692
|
-
cleaned = cleaned.slice(1, -1).trim();
|
|
693
|
-
}
|
|
694
|
-
return cleaned;
|
|
695
|
-
}
|
|
696
859
|
function parseTabId(id) {
|
|
697
860
|
if (!id) return void 0;
|
|
698
861
|
return id;
|
|
@@ -702,19 +865,6 @@ function handleCommandError(error, commandName) {
|
|
|
702
865
|
console.error(pc2.red(`Error executing ${commandName} command: ${msg}`));
|
|
703
866
|
process.exit(1);
|
|
704
867
|
}
|
|
705
|
-
function expandFileRefs(argsJson) {
|
|
706
|
-
return argsJson.replace(/"@(base64)?file:([^"]+)"/g, (_match, base64Flag, filePath) => {
|
|
707
|
-
const absPath = resolve(process.cwd(), filePath);
|
|
708
|
-
let content;
|
|
709
|
-
try {
|
|
710
|
-
content = readFileSync(absPath, "utf-8");
|
|
711
|
-
} catch (e) {
|
|
712
|
-
throw new Error(`\u65E0\u6CD5\u8BFB\u53D6\u6587\u4EF6\u5F15\u7528 "${filePath}": ${e.message}`);
|
|
713
|
-
}
|
|
714
|
-
const value = base64Flag ? Buffer.from(content, "utf-8").toString("base64") : content;
|
|
715
|
-
return JSON.stringify(value);
|
|
716
|
-
});
|
|
717
|
-
}
|
|
718
868
|
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) => {
|
|
719
869
|
const opts = thisCommand.opts();
|
|
720
870
|
if (opts.workspace) {
|
|
@@ -738,42 +888,18 @@ program.command("run <toolName> [args...]").description("\u5411\u6307\u5B9A\u987
|
|
|
738
888
|
\u793A\u4F8B\uFF1Awebmcp-cli run mytool '{"content":"@base64file:./doc.md"}'`
|
|
739
889
|
).action(async (toolName, args, options) => {
|
|
740
890
|
try {
|
|
741
|
-
let
|
|
891
|
+
let fileContent;
|
|
892
|
+
let fileBaseDir = process.cwd();
|
|
742
893
|
if (options.file) {
|
|
743
|
-
const filePath =
|
|
894
|
+
const filePath = resolve2(process.cwd(), options.file);
|
|
895
|
+
fileBaseDir = getFileBaseDir(options.file);
|
|
744
896
|
try {
|
|
745
|
-
|
|
897
|
+
fileContent = readFileSync2(filePath, "utf-8");
|
|
746
898
|
} catch (e) {
|
|
747
899
|
throw new Error(`\u65E0\u6CD5\u8BFB\u53D6\u6587\u4EF6 "${filePath}": ${e.message}`);
|
|
748
900
|
}
|
|
749
|
-
} else if (args && args.length > 0) {
|
|
750
|
-
const firstArg = args[0].trim();
|
|
751
|
-
const cleanedFirstArg = cleanJsonString(firstArg);
|
|
752
|
-
if (cleanedFirstArg.startsWith("{") && cleanedFirstArg.endsWith("}")) {
|
|
753
|
-
finalArgsJson = args.map(cleanJsonString).join(" ");
|
|
754
|
-
} else {
|
|
755
|
-
const obj = {};
|
|
756
|
-
for (const pair of args) {
|
|
757
|
-
const index = pair.indexOf("=");
|
|
758
|
-
if (index === -1) {
|
|
759
|
-
throw new Error(`\u65E0\u6548\u7684\u53C2\u6570\u683C\u5F0F "${pair}"\u3002\u5FC5\u987B\u662F JSON \u5B57\u7B26\u4E32\u6216 key=value \u683C\u5F0F\u3002`);
|
|
760
|
-
}
|
|
761
|
-
const key = pair.substring(0, index).trim();
|
|
762
|
-
let val = pair.substring(index + 1).trim();
|
|
763
|
-
val = cleanJsonString(val);
|
|
764
|
-
try {
|
|
765
|
-
obj[key] = JSON.parse(val);
|
|
766
|
-
} catch {
|
|
767
|
-
obj[key] = val;
|
|
768
|
-
}
|
|
769
|
-
}
|
|
770
|
-
finalArgsJson = JSON.stringify(obj);
|
|
771
|
-
}
|
|
772
|
-
}
|
|
773
|
-
if (!finalArgsJson) {
|
|
774
|
-
throw new Error("\u5FC5\u987B\u63D0\u4F9B\u53C2\u6570\u6216\u901A\u8FC7 -f/--file \u6307\u5B9A\u53C2\u6570\u6587\u4EF6");
|
|
775
901
|
}
|
|
776
|
-
finalArgsJson =
|
|
902
|
+
const finalArgsJson = prepareRunArgsJson(args ?? [], fileContent, fileBaseDir);
|
|
777
903
|
const result2 = await runCommand({
|
|
778
904
|
toolName,
|
|
779
905
|
argsJson: finalArgsJson,
|